Eleventy: React/Vue-like components in nunjucks with macros

I’m experimenting a lot with Eleventy lately, and with nunjucks, since it’s one of the supported template engines.

Today I wanted to create a reusable container macro to avoid repeating the same wrapper over and over. I first tried with a macro like this:

{% macro section(items = []) %}
    <section class="my-section">
            {%- for item in items -%}
                {{ item | safe }}
            {%- endfor -%}
    </section>
{% endmacro %}

It worked. But the downside was that I had to write the HTML in strings. Ugh!

c.section([
      '<p>My first paragraph</p>',
      '<p>My second paragraph</p>'
    ])

So I started reading the official documentation and stumbled upon the call tag. It’s not super-intuitive, but it was exactly what I was looking for.

It allows you to wrap a macro call around some content, so that it’s passed to the macro body. As always an example is worth a thousand words. We change the section definition as such:

{% macro section() %}
    <section class="my-section">
        {{ caller() }} {# This is where the content will be placed #}
    </section>
{% endmacro %}

And we can call it like this:

{% call c.section() -%}
  <p>My first paragraph</p>
  <p>My second paragraph</p>
{%- endcall %}

Much cleaner, and we can also customize the section by passing in some arguments. But this will be the topic of another post.

Leave a Reply

Your email address will not be published. Required fields are marked *