Creating an SVG Library with Twig Macros

Wes Cole
Wes Cole
Aug 23, 2017 · 4 min read

I have been using Timber for building out WordPress projects and have loved how helpful it is to build sites with components and utilize features like macros to make building sites easier.

Before we get into the awesomeness of using macros, we need to set up our SVG icons so that we can easily access them with symbols.

The first thing that you will want to do is create an SVG sprite file.

const rename = require("gulp-rename");
const svgmin = require("gulp-svgmin");
const svgstore = require("gulp-svgstore");
const cheerio = require("gulp-cheerio");
const paths = {
icons: "assets/icons/svg/*.svg"
};
gulp.task("svg", () => {
gulp
.src(paths.icons)
.pipe(svgmin())
.pipe(rename({ prefix: "icon-" })
.pipe(svgstore({ inlineSvg: true })
.pipe(
cheerio({
run: function($, file) {
$("svg").attr("style", "display: none");
$("[fill]").removeAttr("fill");
$("path").removeAttr("class");
},
parseOptions: { xmlMode: true }
})
)
.pipe(gulp.dest("assets/icons")
});
gulp.task("default", ["svg"]);

The above Gulp task will look into the svg directory in and take all SVG files and run through the following tasks:

  1. Minify each SVG file.
  2. Rename adds a prefix in the ID for the specific SVG icon symbol so that we have a consistent naming scheme for all icons.
  3. SVGStore takes all of the separate SVG files and combines them into one using the symbol element.
  4. Cheerio will search the file and remove fills and classes so that all SVG styles are consistent.
  5. Finally, the single SVG Sprite file containing all separate SVG icons will be outputted in the icons directory.

Next, we need to add this SVG sprite file into the footer of the site. I’m typically using WordPress, so I use a function like this to add the file to the footer for all pages. You can add this function to your functions.php file and make sure you update the PARENT_THEME_DIR constant and SVG icons path.

add_action( 'wp_footer', 'add_svg_sprite_to_footer', 9999 );function add_svg_sprite_to_footer() {
$svg_icons = PARENT_THEME_DIR . 'assets/icons/svg-icons.svg';

if (file_exists( $svg_icons )) {
require_once( $svg_icons );
}
}

Ok, we are done setting up, so we can now use Twig macros to easily display SVG Icons wherever we want in our site. If you aren’t familiar with macros, I would recommend reading about them in the Twig Documentation. In essence a macro is similar to a function in that you can output HTML in a reusable element.

Let’s start creating the macro.

{% macro svg(options={}) %}

{% set optons = {
icon: "",
title: "",
desc: ""
} | merge(options) %}
{% set title = options.title ? options.title : options.icon %}
{% set ariaHidden = ' aria-hidden="true"' %}
<svg class="icon icon-{{options.icon}}" {{ariaHidden}} role="img">
<title>{{options.title}}</title>
{% if options.desc %}
<desc>{{options.desc}}</desc>
{% endif %}
<use xlink:href="#icon-{{options.icon}}"></use>
</svg>
{% endmacro %}

Let’s walk through what we are doing with the macro:

  1. The macro takes an options object that we will use later to specify which icon we want to display.
  2. If you want default options, you can assign them in the options object that we create within the macro. Twig will merge the object that you pass into the macro with the defaults that you set.
  3. If a title exists in the object, we are going to use that for the SVG title, otherwise, we use the icon property.
  4. We will output the SVG HTML and pass in all of the appropriate variables from the options object.
  5. You will notice that the <use> tag contains the icon- prefix that we set in the Gulp file. This allows you to pass in the name of the file that you want to access without having to use the prefix. You will see this in action in just a bit.

You will probably want to create a macros directory within your Twig files directory and then I typically create a new file for each macro. Now that we have the macro built, we need to actually use it in our Twig files.

{% import '_macros/_svg.twig' as m_svg %}
{{m_svg.svg({icon: 'facebook-square', title: 'Facebook', desc: 'Facebook Icon'})}}
{{m_svg.svg({icon: 'twitter-square', title: 'Twitter', desc: 'Twitter Icon'})}}
{{m_svg.svg({icon: 'instagram-square', title: 'Instagram', desc: 'Instagram Icon'})}}

I think this code sample will be the easiest to walk through yet. :)

  1. Import the macro from wherever you added it into your Twig directory. The import will assign all macros within that file to the name that you give it in the import. So, we can access the SVG macro by using m_svg.svg.
  2. You will notice that each line under the import is invoking the svg macro and we are passing in an object with all of the appropriate parameters for the icon. One thing to note, the icon property in the object that you pass in should be the same as the name of the single SVG file that you are wanting to display.

That’s it, You know have a macro that you can use throughout all of your Twig files to easily display SVG icons. We’ve run into a few use cases where you might need to still use separate inline SVG files, but for use cases like social media icons, this approach should make working with SVG files a lot easier.

)

Wes Cole

Written by

Wes Cole

Frontend developer exploring the possibilities of the web.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade