
{% for item in items %}
<li class="{{ loop.first ? 'first' : '' }} {{ loop.last ? 'last' : '' }}">
{{ item }}
</li>
{% endfor %}
7. Extend templates with Blocks
<div class="card">
<h2>{{ title }}</h2>
<p>{{ body }}</p>
<a href="#">Read more</a>
</div>
Create a _card.html.twig component
// 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 %}
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.
twig.config:
debug: true
auto_reload: true
cache: false
{{ include('@mytheme/components/_card.html.twig', {
title: node.label,
body: content.body,
url: path('entity.node.canonical', {'node': node.id})
}) }}
6. Conditionals & Loops
path(): Generate internal links
{{ attach_library('mytheme/custom-styles') }}
5. Twig Reusable Components
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
<html>
<head>{% block head %}{% endblock %}</head>
<body>
{% block content %}{% endblock %}
</body>
</html>
Drupal’s core attribute object is accessible through Twig templates, and it’s a powerful way to manage classes and attributes dynamically.
{{ content.field_subtitle|default('No subtitle available') }}
4. Use Twig Functions
{{ include('@mytheme/partials/_button.html.twig', {text: 'Read More'}) }}
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:
In services.yml, set
{{ attach_library('mytheme/hero-banner') }}
<a href="{{ path('entity.node.canonical', {'node': node.id}) }}">
{{ node.title.value }}
</a>
<div class="alert {{ status == 'error' ? 'alert-danger' : 'alert-success' }}">
{{ message }}
</div>
<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
{{ url('entity.node.canonical', {'node': node.id}) }}
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.
Attach libraries:
{% extends "base.html.twig" %}
{% block content %}
<h1>{{ title }}</h1>
{{ body }}
{% endblock %}
{{ 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.
hero-banner:
css:
theme:
css/components/hero-banner.css: {}
js:
js/hero-banner.js: {}