Lullabot: Better SVG Sprite Re-use with Twig in Drupal 8

Planet Drupal - 7. März 2018 - 21:57

There are many advantages to using SVG for the icons on a website. If you’re not familiar with SVG (aka Scalable Vector Graphics) it is an open-standard image format that uses XML to describe graphical images. SVG is great for performance, flexibility, and they look great on high-resolution displays. Though SVG can be really useful, one downside to implementing them can be the effort it takes to reuse them across a Drupal theme in various .html.twig files. SVG markup can be complex due to the number of attributes and, in some cases, there can also be a lot of markup. This issue can in part be mitigated by using inline SVG with the <use> element coupled with SVG Sprites. The combination of these two is a great solution—but unfortunately only gets part of the way to ideal reusability as the markup is still verbose for a single icon, and the number of SVG attributes needed can be hard to remember.

Wouldn’t it be nice if there was a way not to repeat all this code over again wherever we wanted to use an SVG? In this article we outline a way to reuse icons across template files in a Drupal 8 theme by creating a Twig helper function to reuse the markup.

Implementing a custom Twig custom function is fairly accessible to those comfortable with writing custom Drupal themes, but because of the way Drupal separates functionality between what can be defined in a module and what can be defined in a theme, we will need to create a module to contain our custom Twig function. To get started, create a new directory inside <drupalroot>/modules/custom with the following files and directories inside it. For the sake of this article I named the module svgy and the source is available on GitHub.

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

One important thing to note here is that we do not actually have a .module file in our directory. This is not required by Drupal, and the Twig extension which adds our function will be defined as a service and autoload the Svgy.php within the src/TwigExtension directory. Don’t worry if you are unfamiliar with defining custom services in Drupal 8, this article explains all you need to know to get going with what we need for our Twig function.

Now that the directory and file structure is in place, we first need to add the correct metadata to svgy.info.yml:

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

Next the necessary information needs to be added to svgy.services.yml. The contents of this file tells 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 function 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 regarding defining custom Twig extensions is available here. For the purpose of this article the most important part to explain is the inlineSvgMarkup. This function takes two arguments:

  • $name = the unique #id of the icon
  • $title = a string used as the title of the element for better accessibility

When invoked, this function returns a render array with the #type as an inline_template. We use this template type for two reasons: Twig in Drupal 8 has built-in filtering for security reasons and using inline_template allows us to get around that more easily. Since this markup is fairly small and not going to be changed often, we don’t need to create an extra .html.twig file to contain our SVG code.

Implementing the Custom Function In A Theme

Now that the custom twig extension for our icon function is created, how is this implemented in a theme? An example of the following implemented in a theme can be found on GitHub.

The first thing you have to do is add an inline SVG to your theme. The icons inside this SVG should have unique ids. In most situations it is best to generate this SVG “sprite” using something like svgstore as part of your build process. But to keep today’s example simple, I’ve created a simple SVG with two icons and placed it in a theme at <themeroot>/images/icons.svg.

After the icons.svg is in place in the theme you can include it in in the rendered page with the following in the [<themename>.theme](https://www.drupal.org/docs/8/theming-drupal-8/drupal-8-theme-folder-structure#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 automatically. 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 wrapping <span> here is one provided by Drupal 8 core. It applies display: none; to the element. This results in hiding it both visually and from screen readers. Since the individual icons from the SVG will be referenced elsewhere in the page this is the desired outcome.

In the example theme on GitHub, this results in 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 included on the page we can start referencing the individual icons within our SVG sprite with the custom Twig function. After you have cleared Drupal’s cache registry, icons can be added with this:

{{ icon('up-arrow', 'Navigate up') }}

The first argument passed into the function here, up-arrow, is used to reference an existing id in the SVG example included above. The second argument, Navigate up the page, is used as the title of the SVG to better describe contents of the element to users navigating with screen readers.

The resulting markup of this implementation of the icon() function when rendered in a page looks 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 much larger than just the single line where we used the icon() Twig function. This makes it a lot cleaner to reuse icons throughout our .html.twig files. In addition to making templates easier to read and not having to remember all the necessary <svg> attributes, we also ensure consistency in how icons get included throughout the project.

As Drupal themers, it is great to have flexibility like this provided by Twig. If you’re interested in digging deeper into other types of Twig extensions, I encourage you to checkout the Twig Tweak module, which has examples of other helpful Twig extensions.

Have more questions about SVG? Here are some other helpful articles

Renault: Konzeptstudie EZ-GO für den Stadtverkehr der Zukunft

heise online Newsticker - 7. März 2018 - 20:00
Individualverkehr war gestern – in Zukunft kommt man in der Stadt mit Ride-Hailing oder Ride-Sharing von A nach B. Ranault präsentiert ein Konzeptfahrzeug mit großer Einstiegsluke, das seinen Insassen stilvoll durch die Statdt befördern soll.

Human-Robot Interaction: Ethnographie der Roboter

heise online Newsticker - 7. März 2018 - 19:30
Während Ingenieure in aller Welt an neuen Robotern tüfteln, klappt deren Zusammenleben mit den Menschen nicht immer reibungslos. Wissenschaftler wollen deshalb nun Methoden der Ethnographie auf Roboter anwenden.

AMD-Grafiktreiber 18.3.1 zum Download: Optimiert für Final Fantasy XV und Warhammer Vermintide 2

heise online Newsticker - 7. März 2018 - 19:30
Der neue Radeon-Treiber ist für Final Fantasy XV und Warhammer Vermintide 2 optimiert. Überdies behebt er zahlreiche Probleme und verhindert Abstürze in Sea of Thieves.

Clang kompiliert Chrome auch für Windows

heise online Newsticker - 7. März 2018 - 19:30
Das Team hinter dem Browser setzt nun auch für Microsofts Betriebssystem auf das quelloffene Compiler-Frontend. Es ersetzt jedoch Visual Studio nicht komplett, sondern ergänzt Microsofts Entwicklungsumgebung und Build-Werkzeuge.

Zweite Forensikfirma will iOS-11-Unlock besitzen

heise online Newsticker - 7. März 2018 - 19:30
Nach Cellebrite aus Israel behauptet nun auch ein US-amerikanisches Unternehmen, Zugriff auf aktuelle Apple-Geräte mit PIN-Code-Sperre erhalten zu können – gegen mindestens 15.000 US-Dollar.

Frederic Marand: I'm going to Drupal Europe and so should you

Planet Drupal - 7. März 2018 - 19:25

So DrupalCon Europe is out for 2018. But that does not mean a EU-level event does not exist, to bind the community beyond the specialization of DevDays, FrontEnd United, CxO, GovDays, and all the DrupalCamps. Drupal Europe is that event, and to support the community who wants to prove a large Drupal conference can reasonably happen after all the trouble the Drupal Association had with it, the best way it to register for the conference.

ASAP.

So join me there :-)

read more

Promet Source: Promet Delivers Drupal Crash Course for Non-Developers at MidCamp 2018

Planet Drupal - 7. März 2018 - 19:09
It's that time of year again for our favorite Drupal camp - MidCamp Chicago!   Of all the camps in all the cities, this one is always our favorite - because of all the great Drupalists we get to meet but also because it's our hometown camp. 

China kündigt Marktöffnung und fairere Bedingungen an, ausländische Unternehmer skeptisch

heise online Newsticker - 7. März 2018 - 19:00
Abgabensenkung und fairere Marktbedingungen für ausländische Firmen hat Chinas Führung in Aussicht gestellt. Doch westliche Unternehmer zweifeln daran, dass die Versprechungen umgesetzt werden.

Maker Faires 2018: Das sind die Termine

heise online Newsticker - 7. März 2018 - 18:30
Dieses Wochenende geht es mit der Maker Faire Ruhr los: die Maker Faires in Deutschland, Österreich und der Schweiz bieten Makern, Kreativen und Technik-Interessierten wieder die Möglichkeit, Ideen auszutauschen und Selbstgebautes auszustellen.

Nach Start der Falcon Heavy: Tschechischer Astronom für Tesla-Foto ausgezeichnet

heise online Newsticker - 7. März 2018 - 18:30
Elon Musk hat es geschafft: Die Riesenrakete Falcon Heavy hat nicht nur ihren Jungfernflug absolviert, sondern gleich noch ein lohnendes Beobachtungsziel für Astronomen ins All gebracht. Einer wurde nun für seine Aufnahme des Tesla ausgezeichnet.

Drupal Console: Drupal Console 1.7.0

Planet Drupal - 7. März 2018 - 18:15

Drupal Console 1.7.1 is out. The latest release contains several improvements to translations. Support for importing previously exported configuration after a site installation.

US-Behörde verzögert geplante Qualcomm-Übernahme

heise online Newsticker - 7. März 2018 - 18:00
Die US-Behörde für Auslandsinvestitionen CFIUS hat sich im Übernahme-Deal von Qualcomm durch Broadcom eingeschaltet und dadurch möglicherweise die zeitnahe Übernahme verhindert. Qualcomm soll die Behörde eingeschaltet haben.

Forscher finden 34.000 Sicherheitslücken in Smart Contracts auf Ethereum

heise online Newsticker - 7. März 2018 - 17:30
Trotz vieler Warnungen und immer wieder auftretender Probleme hält die Begeisterung für neu angebotene Digitalwährungen (ICOs) an. Dabei sind die damit einhergehenden Sicherheitsfragen noch kaum verstanden.

PCs und Notebooks vor Angriffen schützen

heise online Newsticker - 7. März 2018 - 17:00
Sicherheitslücken lauern nicht bloß in Programmen, Betriebssystemen und Treibern, sondern auch in BIOS, Firmware und Hardware; wer sich besser schützt als andere, ist ein weniger lohnendes Ziel.

Ernstzunehmende Lücken im LTE-Protokoll aufgedeckt, kaum Hoffnung auf Absicherung

heise online Newsticker - 7. März 2018 - 17:00
Zehn neue und neun alte Lücken in der 4G-Technik LTE können nach Belieben kombiniert werden, um Notfall-Nachrichten zu verschicken, Nutzer zu verfolgen und sich als andere Teilnehmer auszugeben. Auch wenn sich diese in einem anderen Land aufhalten.

VW I.D. Vizzion: Volkswagens Auto-Vision

heise online Newsticker - 7. März 2018 - 17:00
Wohl nicht ohne Gedanken an den chinesischen Markt hat Volkswagen die vierte, autonom fahrende VW I.D.-Variante konzipiert. Die auf den ersten Blick fast konventionelle Luxuslimousine fährt ausschließlich mit Batteriestrom und verzichtet auf ein Cockpit.

JBL Link 300 im Test: bester Klang für Google Home

heise online Newsticker - 7. März 2018 - 16:15
Der Link 300 ist JBLs zweitgrößter Lautsprecher mit integriertem Sprachassistenten von Google. Anders als der günstigere Link 20 ist er weder wasserdicht, noch mobil. Dafür punktet er mit sattem Bass und sehr gutem Klang.

Chromatic: Decoupled Drupal – What You Need to Consider

Planet Drupal - 7. März 2018 - 16:00

“Decoupled Drupal” sounds cool and just about everyone else seems to be either doing it or talking about it, so it must be the best solution for you, right? Well, maybe. As with most things, the answer is more nuanced than one might think.

Steam-Umfrage: AMD fällt bei Prozessoren und Grafikchips stark zurück

heise online Newsticker - 7. März 2018 - 15:45
Nur noch neun Prozent der Steam-Umfrageteilnehmer nutzen einen Hauptprozessor oder Grafikchip von AMD zum Spielen. Das geht aus der Steam-Umfrage vom Februar 2018 hervor.