10 Twig Tricks for Better Drupal Theming

Ala Batayneh

Twig is the theming engine that Drupal uses, at least after Drupal 8. It's a templating engine that is developer-friendly and designer-friendly. Its syntax is intuitive, logical, and flexible. In this post, we will cover 10 Twig tricks that will enhance your Drupal theming process, and make theming fun and productive.

 

1. The Debugger

Debugging is the gateway to understanding, so before any tips or tricks, the Twig debugger must be enabled. This will add HTML comments around template suggestions and show which template is being used.

In services.yml, set 

twig.config:
  debug: true
  auto_reload: true
  cache: false

Using dump() for inspection

{{ dump(content) }}
// for cleaner outputs, install Devel and use kint()
{{ kint(content) }}

 

2. Template Suggestion

Drupal generates template suggestions that override templates and let you take granular control over template fields. For instance, the default node.html.twig can be extended to become content-type specific by using node--article.html.twig, or furthermore to the view mode node--article--teaser.html.twig.

Pro tip: Take control over your theme, and don't bloat template with conditional logic, utilize template suggestions instead by add a preprocess hook to your theme:

function mytheme_preprocess_node(&$variables) {
  if ($variables['node']->getType() == 'article' && $variables['view_mode'] == 'teaser') {
    $variables['theme_hook_suggestions'][] = 'node__article__teaser__featured';
  }
}

 

3. Use Twig Filters

Twig allows manipulating variables directly in templates.

// String filters
{{ title|lower }}
{{ title|replace({'Drupal': 'Twig'}) }}

// Date formatting
{{ node.created.value|date("F j, Y") }}


// Length checks
{% if items|length > 3 %}
  <p>There are many items.</p>
{% endif %}

Pro tip: Combine filters with default filter to avoid empty values:

{{ content.field_subtitle|default('No subtitle available') }}

 

4. Use Twig Functions

Twig comes bundled with a variety of helper functions that are ready to be utilized.

path(): Generate internal links

<a href="{{ path('entity.node.canonical', {'node': node.id}) }}">
  {{ node.title.value }}
</a>

url(): Outputs full URLs

{{ url('entity.node.canonical', {'node': node.id}) }}

include(): Reuse partial templates

{{ include('@mytheme/partials/_button.html.twig', {text: 'Read More'}) }}

attach_library(): Load theme libraries

{{ attach_library('mytheme/custom-styles') }}

 

5. Twig Reusable Components

With Drupal's 10 focus on Component-based design approach to theming, utilizing Twig component is a must.

Create a _card.html.twig component

<div class="card">
  <h2>{{ title }}</h2>
  <p>{{ body }}</p>
  <a href="#">Read more</a>
</div>

Include it in other templates:

{{ include('@mytheme/components/_card.html.twig', {
  title: node.label,
  body: content.body,
  url: path('entity.node.canonical', {'node': node.id})
}) }}

 

6. Conditionals & Loops

Conditional attributes can be used to keep minimal and clean

<div class="alert {{ status == 'error' ? 'alert-danger' : 'alert-success' }}">
  {{ message }}
</div>

Looping with helpful variables:

{% for item in items %}
  <li class="{{ loop.first ? 'first' : '' }} {{ loop.last ? 'last' : '' }}">
    {{ item }}
  </li>
{% endfor %}

 

7. Extend templates with Blocks

Twig supports inheritance, for instance a Base template base.html.twig

<html>
  <head>{% block head %}{% endblock %}</head>
  <body>
    {% block content %}{% endblock %}
  </body>
</html>

could extend a child template

{% extends "base.html.twig" %}

{% block content %}
  <h1>{{ title }}</h1>
  {{ body }}
{% endblock %}

This also make building a component-based theme easier. 

 

8. Advanced Attributed

Drupal's core attribute object is accessible through Twig templates, and it's a powerful way to manage classes and attributes dynamically.

<div{{ attributes.addClass('node', 'node--' ~ node.bundle) }}>
  {{ content }}
  // You could also merge attributes
  {{ title_attributes.addClass('page-title') }}
</div>

 

9. Performance Considerations

  • Disable debugger in production
  • Use include or embed instead of duplicating markup
  • Cache output

 

10. Attach Libraries

In Drupal 10, Twig themes can be combined with third-party libraries in an extremely modular way:

Attach libraries:

{{ attach_library('mytheme/hero-banner') }}

Define library in mytheme.libraries.yaml

hero-banner:
  css:
    theme:
      css/components/hero-banner.css: {}
  js:
    js/hero-banner.js: {}