Better SVG Sprite Re-use with Twig in Drupal 8

KrishaWeb
6 min readMay 9, 2018

--

There are numerous advantages to utilizing SVG for the icons on a website. If you’re not knowledgeable about SVG (aka Scalable Vector Graphics) it is an open-standard image format that uses XML to explain visual photos. SVG is great for performance, flexibility, as well as they look wonderful on high-resolution screens. Though SVG could be actually beneficial, one drawback to executing them could be the effort it requires to reuse them across a Drupal theme in various.html.twig files. SVG markup could be complex due to the number of attributes as well as, in many cases; there could additionally be a lot of markup. This issue could partly be reduced by using inline SVG with the <use> element paired with SVG Sprites. The mix of these 2 is a wonderful option — but sadly only obtains component of the way to excellent reusability as the markup is still verbose for a single icon, and the number of SVG attributes needed could be tough to keep in mind.

Would not it be nice if there was a method not to duplicate all this code over once again wherever we wished to use an SVG? In this article we detail a way to reuse icons throughout template files in a Drupal 8 theme by creating a Twig helper function to reuse the markup.

Applying a personalized Twig customized function is relatively accessible to those comfy with writing custom Drupal themes, however as a result of the means Drupal divides performance in between just what can be specified in a module as well as just what could be specified in a theme, we will certainly need to create a module to contain our personalized Twig function. To get started, create a new directory inside <drupalroot>/ modules/custom with the complying with files as well as directories inside it. For this short article I called the module svgy and the source is offered on GitHub.

svgy
├── src
│ └── TwigExtension
│ └── Svgy.php
├── svgy.info.yml
└── svgy.services.yml

One essential point to note here is that we do not in fact have a.module file in our directory. This is not needed by Drupal, as well as the Twig extension which adds our function will be defined as a service and also autoload the Svgy.php within the src/TwigExtension directory. Don’t worry if you are unfamiliar with defining custom solutions in Drupal 8, this post describes all you should understand to obtain selecting what we need for our Twig function.

name: svgy
type: module
description: Add a Twig function to make using inline SVG easier.
core: 8.x

Now that the directory and file structure remains in place, we first should add the right metadata to svgy.info.yml:

Next the necessary information needs to be added to svgy.services.yml. The contents of this file informs Drupal to autoload the Svgy.php file in the src/TwigExtension directory:

services:
svgy.twig.extension:
class: Drupal\svgy\TwigExtension\Svgy
tags:
— { name: twig.extension }

Now that Svgy.php is going to be loaded, add the code for our Twig feature into it:

<?php

namespace Drupal\svgy\TwigExtension;

class Svgy extends \Twig_Extension {

/**
* List the custom Twig fuctions.
*
* @return array
*/
public function getFunctions() {
return [
// Defines a new ‘icon’ function.
new \Twig_SimpleFunction(‘icon’, array($this, ‘getInlineSvg’)),
];
}

/**
* Get the name of the service listed in svgy.services.yml
*
* @return string
*/
public function getName() {
return “svgy.twig.extension”;
}

/**
* Callback for the icon() Twig function.
*
* @return array
*/
public static function getInlineSvg($name, $title) {
return [
‘#type’ => ‘inline_template’,
‘#template’ => ‘<span class=”icon__wrapper”><svg class=”icon icon — {{ name }}” role=”img” title=”{{ title }}” xmlns:xlink=”http://www.w3.org/1999/xlink"><use xlink:href=”#{{ name }}”></use></svg></span>’,
‘#context’ => [
‘title’ => $title,
‘name’ => $name,
],
];
}
}

More information relating to defining custom Twig extensions is offered right here. For the objective of this article one of the most important part to explain is the inlineSvgMarkup. This function takes two arguments:

$ name = the special #id of the icon

$ title = a string used as the title of the element for better ease of access

When conjured up, this function returns a render array with the #type as an inline_template. We utilize this template type for 2 factors: Twig in Drupal 8 has built-in filtering for security reasons as well as use of inline_template permits us to get around that even more conveniently. Because this markup is rather small as well as not going to be changed usually, we do not should develop an extra html.twig file to include our SVG code.

Executing the Custom Function in a Theme

Now that the custom twig extension for our icon function is developed, just how is this executed in a theme? An instance of the following executed in a theme could be located on GitHub.

The initial point you have to do is add an inline SVG to your theme. The icons inside this SVG must have unique ids. In the majority of circumstances it is best to generate this SVG “sprite” using something like svgstore as part of your build process. But to keep today’s instance simple, I’ve produced a simple SVG with 2 icons as well as positioned it in a theme at <themeroot>/ images/icons. svg.

After the icons.svg remains in place in the theme you can include it in the rendered web page with the following in the themename.theme file:

function <theme_name>_preprocess_html(&$variables) {
// Get the contents of the SVG sprite.
$icons = file_get_contents(\Drupal::theme()->getActiveTheme()->getPath() . ‘/images/icons.svg’);

// Add a new render array to page_bottom so the icons
// get added to the page.
$variables[‘page_bottom’][‘icons’] = array(
‘#type’ => ‘inline_template’,
‘#template’ => ‘<span class=”hidden”>’ . $icons . ‘</span>’,
);
}

This appends a new render array to the page_bottom variable that is printed out inside Drupal core’s html.html.twig template file. If you haven’t overridden this template in your theme, the icons will get printed out immediately. If you have overridden html.html.twig in your theme — just make sure you are still printing page_bottom inside it: ({{ page_bottom }} is all you need.

The.hidden class that is used in the covering <span> here is one provided by Drupal 8 core. It uses display: none; to the element. This results in concealing it both visually as well as from screen readers. Because the individual icons from the SVG will be referenced elsewhere in the page this is the desired result.

In the example theme on GitHub, this results to the following output on the page:

<span class=”hidden”><?xml version=”1.0" encoding=”UTF-8"?>
<svg viewBox=”0 0 130 117" version=”1.1" xmlns=”http://www.w3.org/2000/svg" xmlns:xlink=”http://www.w3.org/1999/xlink">
<polygon id=”down-arrow” fill=”#50E3C2" points=”64.5 117 0 0 129 0"></polygon>
<polygon id=”up-arrow” fill=”#50E3C2" points=”65.5 0 130 117 1 117"></polygon>
</svg></span>

Now that the SVG “sprite” is consisted of on the page we could begin referencing the individual icons within our SVG sprite with the custom twig feature. After you have actually cleared Drupal’s cache registry, icons could be added with this:

{{ icon(‘up-arrow’, ‘Navigate up’) }}

The initial debate passed into the function below, up-arrow, is utilized to reference an existing id in the SVG example consisted of above. The second argument, Navigate up the page, is used as the title of the SVG to better explain contents of the elements to users navigating with screen readers.

The resulting markup of this implementation of the icon() function when rendered in a page appears like:

<span class=”icon__wrapper”>
<svg class=”icon icon — up-arrow” role=”img” title=”Navigate up” xmlns:xlink=”http://www.w3.org/1999/xlink">
<use xlink:href=”#up-arrow”></use>
</svg>
</span>

As you can see, the resulting markup is a lot larger compared to just the single line where we used the icon() Twig function. This makes it a lot cleaner to recycle icons throughout our html.twig files. Along with making templates simpler to read as well as not having to remember all the necessary <svg> features, we additionally make sure consistency in exactly how icons obtain included throughout the project.

As Drupal themers, it is fantastic to have adaptability such as this provided by Twig. If you have an interest in digging deeper into other sorts of Twig extensions, I motivate you to checkout the Twig Tweak module, which has instances of various other handy Twig extensions.

Have more questions about SVG?Want to work with top Drupal experts for a modular site redesign with immense flexibility? Contact our Drupal web development services today or email us at info@krishaweb.com.

--

--

KrishaWeb
KrishaWeb

Written by KrishaWeb

A Full-Service Digital Agency offering Web Design, UI UX Design, Open Source Development, Framework Development, and Digital Marketing to global clients.

No responses yet