understanding Twig in Drupal 8

At miggle we have developed multiple sites within Drupal 8, ranging from basic brochure style (like our Acquia Engage award winning Think Nation site) to complex sites which integrate with external platforms like The Student Room, but in all cases of Drupal 8 sites the front-end theming is achieved with Twig.

what is Twig?

Twig is a modern template engine for PHP 

  • Fast: Twig compiles templates down to plain optimized PHP code. The overhead compared to regular PHP code was reduced to the very minimum.
  • Secure: Twig has a sandbox mode to evaluate untrusted template code. This allows Twig to be used as a template language for applications where users may modify the template design.
  • Flexible: Twig is powered by a flexible lexer and parser. This allows the developer to define its own custom tags and filters, and create its own DSL.

separating the front-end and back-end (decoupled architecture)

Drupal 8 takes advantage of having a decoupled system, meaning that front-end developers now have full control of the sites rendered markup allowing them to give the user a better experience and cleaner markup. As a front-end developer it also means I do not need to know the full in and outs of the systems architecture to create templates though I do have a good understanding still - you can see this from my dev diary.

helpful twig markup

this markup is for use within a page template, page.html.twig

render a region
{{ page.content }}
render the current years date (useful for copyright)
© {{ 'now'|date('Y') }}

this markup is for use within a node template, node.html.twig

render the node title
{{ label }}
render a specific field
{{ content.field_name }}
render content without a field
{{ content|without('field_name_one', 'field_name_two') }}
formatting dates
{{ node.createdTime|date(format='d F Y') }}
create a relative path
{{ path('entity.node.canonical', {'node': node.id }) }}
create an absolute path
{{ url('entity.node.canonical', {'node': node.id}) }}
shared markup

If you ever find you need to have the same piece of content across multiple node templates you can create a twig file & then included it within a template. 

Create a new file, e.g.


Within your node template you can now include this with.

{% include '@themename/includes/shared-content.html.twig' %}
add attributes to field items e.g. field.html.twig (Anywhere where you print {{ item.content }})
{{ item.content|merge({'#options' : {'attributes': {'class': ['class--one', 'class--two']}}}) }}

the below markup is global & useful for any template

Add classes (inline)
{{ attributes.addClass('class--one', 'class--two') }}
add classes (dynamically)
  set classes = [
    node.isPromoted() ? 'is-promoted',
    node.isSticky() ? 'is-sticky',
    not node.isPublished() ? 'is-unpublished',
    view_mode ? view_mode|clean_class,
{{ attributes.addClass(dynamic_classes) }}


If you want to take back control of your web sites and applications then get in touch with miggle to see how we can deliver operational freedom for you in Drupal.