Including SVG icons in a Drupal 8 theme

May 01, 2016

I got started with task runners a while ago using Grunt, thanks to an excellent 24 ways article by Chris Coyier. Lately I’ve been using Gulp more, and all the cool kids seem to be going that way, so for the Drupal 8 version of The Gallery Guide, I’ve decided to use Gulp.

Since hearing Chris Coyier talk about SVG icon systems, I’ve been meaning to implement them in my own workflow. I’ve written about a similar setup for Jekyll on the Capgemini engineering blog, and wanted to apply something similar to this site.

The Gulp setup for this project is almost identical to the one described in that post, so I won’t go into too much detail here, but in the spirit of openness that’s guiding this project, the gulpfile is on Github.

In short, there’s a directory of SVG icons within the theme, and there’s a Gulp task to combine them into a single file at images/icons.svg. Then the contents of that file is injected into the page using a preprocess function. There’s a slight gotcha here - if the value is added directly, without going through the t() function, then it automatically gets escaped to block cross-site scripting. It doesn’t seem to make sense, according to the documentation, but I needed to pass the value in without any prefix character:

function gall_preprocess_page(&$variables) {
  $svg = file_get_contents(drupal_get_path('theme', 'gall') . '/images/icons.svg');
  $variables['svg_icons'] = $svg;
}

If we were working with user-supplied content, this would be opening up a dangerous attack vector, but given that it’s content that I’ve created myself in the theme, it’s safe to trust it.

Having done that, in the page.html.twig template, the variable is available for output:

{{ svg_icons | raw }}

Then these files can be referenced - here’s a snippet from region--header.html.twig:

<a href="https://www.twitter.com/thegalleryguide" title="Follow us on Twitter">
  <svg class="icon">
    <use xlink:href="#twitter"></use>
  </svg>
</a>

Part of me feels like there should be a more Drupal-ish way of doing this, so that the links are part of a menu. But given that this is my own project, and changing the icons would require a code change, it doesn’t feel so bad to have them hard-coded in the template.