SVGs and WordPress [part one]

The Scalable Vector Graphic, or SVG, has been around since 1999. Up until recently it felt a bit unaccessible to me, however when redoing this site, I wanted to learn more about the format. It can be leveraged in many ways: embedding directly into the HTML, referencing as an image – some even base64 encode it into their CSS as a background image.

What if you wanted to upload an SVG into WordPress so you could use it in your posts and pages or as a featured image? Embedding the SVG code directly into the text editor results in it getting stripped out. It is possible to upload the SVG into the media library and call that into your editor, but you’ll need a plugin and you’ll have to take an extra step to give the SVG dimensions or it will default to 1px by 1px.

test

This feature comes with it’s own unique security risks. You can learn more about the format and its nuances here: https://www.youtube.com/watch?v=v-a77QdoK2I

The best solution I’ve found to date is uploading them to your media library and inserting them as a media type into your post. However, there’s a bit of modification you’ll need to do first. So far, the best starting point I’ve found is the Scalable Vector Graphics (SVG) plugin for WordPress. This doesn’t fulfill the entire solution we want but it allows uploading of SVGs to the media library. I was able to embed my logo into this post using the plugin but I did need to give it a defined width manually, as it defaults to 1 pixel for both width and height. Which brings me to:

What this plugin doesn’t do

  1. It doesn’t enable the SVGs to use image sizes, core or custom.
  2. It doesn’t show a rendering of the SVG in the Media Library grid or Insert Media overlay – instead the SVG shows as a file icon.
SVG in Media Library

An SVG in the Media Library

That first point is crucial; if I’m going to be using SVGs for Featured Images or embedding them into my pages and posts I don’t want to have to manually set the width every time and it’s not possible to work with Featured Images without using the full size for the SVG, which defeats some of the best aspects of having the SVG to begin with.

What I want to try to accomplish is enabling the SVG to utilize the image sizes (thumbnail, medium, large) defined by WordPress and also custom image sizes, if defined.

First Pass

For starters, I’m going to focus on the Featured Image functionality. This will not work as expected with SVGs, even with the aforementioned plugin, unless you’re only specifying the full size image; this is not very useful. What I want to do is filter the post thumbnail, detecting an SVG file type and tweaking the HTML a bit to get the SVG to adhere to the image sizes defined on the site. I’ll be using the `post_thumbnail_html` filter and a function to grab the image sizes with dimensions from the WordPress codex pages:

function get_image_sizes( $size = '' ) {
  global $_wp_additional_image_sizes;

  $sizes = array();
  $get_intermediate_image_sizes = get_intermediate_image_sizes();

  // Create the full array with sizes and crop info
  foreach ( $get_intermediate_image_sizes as $_size ) {
    if ( in_array( $_size, array( 'thumbnail', 'medium', 'large' ) ) ) {
      $sizes[ $_size ]['width'] = get_option( $_size . '_size_w' );
      $sizes[ $_size ]['height'] = get_option( $_size . '_size_h' );
      $sizes[ $_size ]['crop'] = (bool) get_option( $_size . '_crop' );
    } elseif ( isset( $_wp_additional_image_sizes[ $_size ] ) ) {
      $sizes[ $_size ] = array(
        'width' => $_wp_additional_image_sizes[ $_size ]['width'],
        'height' => $_wp_additional_image_sizes[ $_size ]['height'],
        'crop' => $_wp_additional_image_sizes[ $_size ]['crop'],
      );
    }
  }

  // Return only one size, if found
  if ( $size ) {
    if ( isset( $sizes[ $size ] ) ) {
      return $sizes[ $size ];
    } else {
      return false;
    }
  }

  return $sizes;
}

This custom function leverages the above, modifying the HTML for SVGs to enable display for the post thumbnail size specified:

function featured_svg( $html, $post_id, $post_thumbnail_id, $size, $attr ) {
  // If this isn't an SVG, return early
  if ( get_post_mime_type( $post_thumbnail_id ) !== 'image/svg+xml' ) {
    return $html;

  } else {
    $attributes = get_image_sizes( $size );

    // Use some regular expressions to replace the width and height attributes
    $html = preg_replace( '/(height)="d*"s/', 'height="' . $attributes['height'] . '"', $html );
    $html = preg_replace( '/(width)="d*"s/', 'width="' . $attributes['width'] . '"', $html );

    return $html;
  }
}
add_filter( 'post_thumbnail_html', 'featured_svg', 10, 5 );

In part two I’ll explore hard cropping and possibly crop positioning with SVGs.

1 thought on “SVGs and WordPress [part one]”

  1. vince.fr says:

    Hey Jason,

    I just started using svg and your post saved me : it’s working fine.
    2 days and you already helped somebody, you rock 🙂

    I’m looking forward to read your next post !

    cheers,
    Vincent

Leave a Reply

Your email address will not be published. Required fields are marked *