If we look at our themes
templates folder, we can see that we have created quite a few Twig templates. While having an abundance of Twig templates is not necessarily a bad thing, it does become a little bit harder to manage our code.
One powerful feature of Twig templates is that they allow us to address this by extending or sharing markup between each template. This is great for global sections of markup. For example, the header and footer of our page never change, so why have the same markup in both page
templates?
Twig {% extends %}
allows us to share markup between templates by extending a template from another one. In our case, we could use this Twig function by extending the page.html.twig
template from our page--front.html.twig
template.
Begin by opening up the page--front.html.twig
template in our favorite editor and add the following markup to the very top of our page:
New markup
{% extends 'themes/octo/templates/page.html.twig' %}
Now, if we were to save our template, clear Drupal's cache, and browse to our homepage, we would see Drupal complaining about how a template that extends another cannot have a body. The reason is that, while we are extending the page.html.twig
template, we are not exposing any Twig blocks, which is a requirement for reusing sections of markup.
Twig blocks, not to be confused with Drupal Blocks, are just containers that we can place around a section of content which allow another template to be able to replace the content within it. So how does this work exactly?
First, a Twig block is referenced using the following syntax:
{% block content %} some content or markup {% endblock %}
In this example, some content or markup could be replaced from another template extending the parent template. It's not important what you call your {% block %}
, just as long as you're consistent.
Continuing with extending the page.html.twig
template, begin by adding the following Twig block around our <main>
content section:
New markup
{% block content %} <main>…</main> {% endblock %}
Now we have a Twig block that can be referenced from within page--front.html.twig
so that any content within the <main>
content element can potentially be replaced.
Next, we will want to edit page--front.html.twig
and first remove the <header>
and <footer>
blocks, as we will inherit those from the page.html.twig
template:
New markup
{% extends 'themes/octo/templates/page.html.twig' %} {% block content %} {{ attach_library('octo/flexslider') }} {{ attach_library('octo/scroll-to') }} <section class="intro" id="id2524section1" data-speed="5" data- type="background" style="background-position: 50% 0px;"> <div class="overlay"> <div class="headline"> {{ page.headline }} </div> </div> <a href="#" id="goto-section2" class="arrow-down">Get started</a> </section> <main role="main" class="main"> <div class="layout-content"> <section id="section2" class="section"> <div class="container"> {{ page.before_content }} </div> </section> </div> </main> {% endblock %}
Now, if we save both templates, clear Drupal's cache, and refresh our homepage, we should see that our markup is being output correctly. So here's a quick explanation of what's happening here:
page.html.twig
including the header, footer, and Twig block. This is why we still see the header and footer of our website being displayed. However, we now only have to worry about managing that markup from a single template.page--front.html.twig
template, it is overriding the markup in page.html.twig
and displaying the proper content for our homepage.This is very powerful, as we can start to look at any content that is repeated across our templates and, with some proper planning, use {% extends %}
and {% block %}
to manage our markup.
This is just the surface of how Twig can be extended; for more information and more details of all the possibilities, take a look at the documentation at Sensio Labs: http://twig.sensiolabs.org/.