Skip to content

Building a Button Macro in Nunjucks


Nunjucks is a templating language that I use in many of my static site projects. It has a lot of capabilities, but the most powerful and useful one is macros. Macros are similar to React.js components in that you create a chunk of code, and then pass data into those components. This is useful for my website, where I often have elements repeated across many pages, and would rather manage 1 object, versus editing each individual instance.

What we'll build

{% macro button(buttonUrl, prefixIcon, text, suffixIcon) %}
{% set prefixUrl = 'svgs/' + prefixIcon + '.svg' %}
{% set suffixUrl = 'svgs/' + suffixIcon + '.svg' %}

<div class="button-wrapper">
    <a href="{{buttonUrl}}" class="button
      {% if prefixIcon %} has-icon-left {% endif %}
      {% if suffixIcon %} has-icon-right {% endif %}
    ">
        {% if prefixIcon %}{% include prefixUrl %}{% endif %}
        {{text}}
        {% if suffixIcon %}{% include suffixUrl %}{% endif %}
    </a>
</div>
{% endmacro %}

This macro will render a button with the provided text, linking to the correct URL, and adding an icon in the beginning or end of the button.

Creating a macro

Macros are individual files that have parameters set. Create a new file and name it button.njk. Since we’re making a button, I called this macro button. In addition to naming, we must set what variables the macro can receive. For this solution we have 4:

{% macro button(buttonUrl, prefixIcon, text, suffixIcon) %}
	Button code goes here
{% endmacro %}
  1. buttonURL - what URL is the button going to?
  2. prefixIcon - what icon should be added to the beginning of the button?
  3. text - what is the button text?
  4. suffixIcon - what icon should be added to the end of the button?

Handling SVGs

All of the SVGs used on this website are housed in a folder called /svgs. I treat these as partials, and use them to include via Nunjucks like so: {% include 'svgs/ArrowLeft.svg' %}. Since the button macro will receive either prefixIcon or suffixIcon, we’ll need to build some variables to help wire up the include statement:

{% set prefixUrl = 'svgs/' + prefixIcon + '.svg' %}
{% set suffixUrl = 'svgs/' + suffixIcon + '.svg' %}

For example, if I set my prefixIcon as ArrowLeft, then prefixURL becomes svgs/ArrowLeft.svg - providing a path for my include statement.

Setting CSS classes

I prefer to append classes to my buttons to style them appropriately. If a button has a prefixIcon it receives the css class .has-icon-left. Similarly, if a button has a suffixIcon, it receives the css class .has-icon-right.

<a
  href="{{buttonUrl}}"
  class="button {% if prefixIcon %} has-icon-left {% endif %} {% if suffixIcon %} has-icon-right {% endif %}"
>
  Button
</a>

Button contents

Inside the button itself are 3 contents:

  1. prefixIcon - the prefix icon.
  2. {{text}} - the button text, which is passed into the macro.
  3. suffixIcon - the suffix icon.

Since I want flexible buttons, I use if statements to render the appropriate icons, depending on if prefixIcon or suffixIcon are passed an SVG name. We’re also making use of Nunjucks include, which simply renders the content of the file.

{% if prefixIcon %}{% include prefixUrl %}{% endif %}
{{text}}
{% if suffixIcon %}{% include suffixUrl %}{% endif %}

Using the macro

Now that my macro is created, it can be used on any nunjuck page, or even markdown file. To use any macro, it must first be imported on the page you wish to use it, ideally near the top:

{% from 'macros/button.njk' import button %}

This imports the macro and allows you to call it like so:

{
  {
    button('/about', '', 'More on Me', 'Smiley')
  }
}

In the above example, a button is rendered that links to my about page, with the button text “More on Me”, using a suffixIcon of Smiley.svg. Since I want the SVG to be on the right, the prefixIcon is left empty.

When to use macros

Macros provide the potential of streamlining your website code, particularly when you managing a large static site with lots of repeating elements. In general, it’s good practice to use a macro if:

  • An element is repeated 2 or more times on a website.
  • An element can be customized with some parameters (e.g. suffixIcon and prefixIcon.
Brandon
          Templar at his desk
Hello! I’m Brandon Templar, a product designer in Washington, D.C.

I am a designer, photographer, and tech enthusiast that has decided to write more about my thoughts and process. Thanks for following along!