Using SVGs in WordPress

SVGs are basically the bomb-diggety for vector images on the web. They’re crisp and clean at any size or resolution, making them perfect for icons, line art, or other vector artwork. Unfortunately, using SVGs in WordPress is not supported by default. This post shows you how to fix three significant issues with using SVGs in WordPress: uploading SVGs, displaying SVGs in the Editor and custom fields, and inlining SVG code in a post or page template.

Allowing SVGs in WordPress Uploader #

WordPress, however, doesn’t allow you to upload SVGs. By default, it treats them as a security risk (I’d assume this has something to do with the possibility of executing code through SVG’s XML file format, but maybe someone can leave a more detailed answer in the comments…). Step one to using SVGs in WordPress is to give the Media Library Uploader permission to upload them. The following PHP snippet (pasted in your theme’s functions.php file) will do that:

function svg_mime_types( $mimes ) {
  $mimes['svg'] = 'image/svg+xml';
  return $mimes;}
add_filter( 'upload_mimes', 'svg_mime_types' );

That snippet comes from CSS-Tricks.com.

Displaying SVGs in WordPress Dashboard #

Default display of SVGs in WordPress custom field

Whoops, this SVG is huge!

Now that you can successfully upload SVGs to your Media Library, you’re about to run into a pretty nasty display problem: the SVG is either too small or too big. If you put the SVG in the editor inline, you’ll end up with the default height/width attributes set to 1px × 1px: practically invisible. If, on the other hand, you’re using an SVG in a custom field, the image becomes huge, filling all the possible width of the column (and a proportional height). To fix this, we need to add some CSS to WordPress’s Dashboard. The following PHP snippet (again, added to functions.php) will accomplish that:

function svg_size() {
  echo '<style>
    svg, img[src*=".svg"] {
      max-width: 150px !important;
      max-height: 150px !important;
    }
  </style>';
}
add_action('admin_head', 'svg_size');

What we just did was insert a small CSS declaration into every Dashboard page. The selector finds <svg> elements, as well as images with .svg in their src attribute. It then overrides their default attributes (1px × 1px in the Editor, no limits in a custom field) and fits them all into a 150px × 150px box.

Improved display of SVGs in WordPress custom field

Ah, this is much better!

Note: this is only a problem if you’re optimizing your SVGs with a tool that removes the height and width attributes. You should optimize, of course! Just be aware that if your optimizer removes height/width, you’ll need to use CSS to control the layout size of the SVG on the front-end as well as here in the Dashboard.

Inlining SVGs in WordPress Themes #

Now let’s push a little farther. Let’s take a common SVG case use and solve another WordPress-related SVG issue. We’ll pretend for a moment that we’re building a website for a manufacturing company and we’re using a custom post type for each “step” in their process. Each step has an icon that’s an SVG, so we add a custom field for “Step Icon” to the post type. We want those icons to change color on hover, however. The normal dark blue color should become a medium gray. In order to transition colors on :hover with only CSS, we need to inline the SVG as XML in the page. Using <img src=“image.svg”> or using an SVG background-image won’t allow us to control the colors with CSS. Assuming you’re using the ACF plugin for your custom fields, the following PHP snippet belongs in the template file you use for displaying process steps where you want to inline the SVG file:

if ( get_field( 'step_icon' ) ) {
  $icon = get_field( 'step_icon' );
  if ( strpos( $icon, '.svg' ) !== false ) {
    $icon = str_replace( site_url(), '', $icon);
    print '<div class="step-icon">';
    include(ABSPATH . $icon);
    print '</div>';
   }
}

Of course, if you’re using a different plugin for your custom fields (Types, Pods, etc), you’ll need to change get_field() to whatever function that plugin provides (or use WP’s core get_post_meta() function). That snippet checks to make sure the image is really an SVG, then strips out the WP site_url text. (This is necessary because the include() function on a full http[s] url is a cross-site-scripting vulnerability.) The include() function prints the SVG as XML to your page’s source. The following CSS (or something similar) in your style.css will allow you to change the color on hover:

.step-icon svg path,
.step-icon svg polygon {
  fill: #383b52; /* Your color here. */
}
.step-icon:hover svg path,
.step-icon:hover svg polygon {
  fill: #444; /* Your color here. */
}

Now you should get this delightful hover effect:

CSS Hover Effects for Inline SVGs in WordPress

Conclusion #

There you have it: three code snippets to allow you to (1) upload SVGs to your WordPress Media Library, (2) display those SVGs nicely in Dashboard, and (3) inline those SVGs in WordPress theme files. You’ll want to be aware that SVGs aren’t supported by IE8 and down, so you’ll need to work out a fallback if a missing SVG image would create a usability or accessibility problem.

If you’ve got questions or other great ideas for using SVGs in WordPress, please leave a comment!