Migrating to Drupal 8 part 2: template central

Migrating to Drupal 8 part 2: template central

Read part 1

In our last post, we started our new Drupal 8 site by building out our new theme. We set up the file structure and created the necessary files that allows us to enable our theme and begin building. In part two, we’re going to dive into the templating system and show you how to start coding with Twig.

In the theme we built in the last post, we defined our base class to be core’s stable theme. Stable is actually the default ‘base theme,’ however it’s worth choosing a base theme directly so that you’re never just using core directly. We can then use stable’s templates as a starting point for our own theme. Head into stable’s directory in `/core/themes/stable` and copy the `templates` folder into the theme’s folder. This will give us a foundation to start modifying and updating templates, and we don’t have to waste time writing them all from scratch.

Drupal will look through your theme’s templates and use the first one it finds, so it doesn’t care how you choose to structure your template folder. You can organize them any way that you’d like. I kept the default organization from the stable theme, but by all means, structure them how you like. A SMACSS-like approach is also a fantastic idea.

Getting twiggy

Before we jump into a specific template, let’s take a second to talk about Twig itself. Twig is a templating language new to Drupal 8 core that allows us to produce any specific markup we would like. We don’t have to rely upon whatever Drupal chooses to give us. With Twig, the developer has full control over what gets printed to the DOM.

Let’s open up the single page template and take a look around `templates/layout/page.html.twig`. Here we are defining the basic structure of a page. You’ll see the HTML markup with some basic Twig and two types of blocks, `{% … %}` and `{{ … }}`.

The `{% … %}` blocks have been described as the “do something” blocks. They are performing an action/function, whereas the `{{ … }}` blocks are “saying something”, and output whatever content is placed inside the braces.

As you can see in the `page.html.twig` file we’re looking at, we’re printing our header, main body content, and footer enclosed in their respective HTML tags. These three areas - header, content, and footer - are actually three of the default `regions` that exist in Drupal. If you read the comments at the top of the `page.html.twig` file, it actually lists all of the default regions that can be output within this file.

Each of those regions then output using the `region.html.twig` template (unless a more specific one is found). Most of the time however, you’ll want to add some custom regions of your own. This can easily be done by adding new regions into your `.info.yml` file and then printing out the new region in the `page.twig.html` file. However, if you do declare any regions in your theme, even just a single custom region, you must declare any and all regions that will be used.

Let’s say we wanted a region that was below our content but still above the footer, we would just create a new region called `below_content`, and then print it out within our template using the `{{ … }}` syntax! Let’s do that now. Head back to your `.info.yml` file, and define the new region.

Now we can go back to our template, and print out the new region!

Now we have our templates set up, our regions defined, and we know how to print out our basic content.

Debugging and finding the right template

When you start pushing blocks and content to your pages, you’ll need to know which specific templates are outputting that content. Thankfully, we can simply turn on template debugging and it will output comments within our HTML document that tells us exactly which template is being used, and give us suggestions about new templates you could create that would take over for that piece of content.

In `sites/default/services.yml` under `twig.config:` set the `debug:` flag to `true`, then be sure to clear your cache with `drush cr` or within the admin panel under Configuration -> Performance. Now head back to one of your pages and inspect the source to see the comments surrounding your HTML elements.

Printing variables within your templates

If you’re using core templates as your base, each template file should include comments at the top that describes the basic variables that are available to you. Our new region, for example, would be using the default `region.html.twig` file.

As you can see, our region has three available variables that we can print out. If you would like to see what’s inside a variable, you can use the `dump()` function: `{{ dump(variable) }}`. If you have the Devel’s kint submodule, you can use `{{ kint(variable) }}` for an accordion style view of the output.

If you don’t know what variables you can use, or you’re looking for something a bit more specific to output, you can use `{{ dump() }}` to see all the available variables and their content. If you’d simply like to see the available variable keys without all the content, use `{{ dump(_context|keys) }}`. The `context` references the current context or current location that you’re in, and contains all the variables passed (So `dump()` and `dump(_context)` would give you the same result).

Generally if you are within a block or a field, and you’re looking for a specific piece of content within one of your blocks, you can dive into the `content` key and you should be able to find what you’re looking for. However if you’re at the region level, the content works a little different. When you’re outputting a region, the `content` is actually an HTML string of each block being output within that region. Therefore you have to navigate through the `elements` key and find the specific block.

If you can’t find exactly what you’re looking for looking through the keys, you’ll likely have to do some custom work in a preprocess function.

Twig functions/filters

Now that we’ve explored the basic functionality within the Twig templates, let’s look at some more of the functions that we can use. There are quite a lot of them, and you can go through the Twig filters, Twig functions, and Drupal.org for the full list, but I’ll touch on a few that we found quite useful.


Filters are different than functions in that they are used to modify variables that you currently have access to. Filters are added after the variable name and a pipe symbol ( | ). Filters may have arguments and can be chained.

`safe_join`: when you need to join several strings together with a specific separator, `{{ items|safe_join(‘, ‘) }}`

`clean_class` and `clean_id`: these filters clean a string for use as a valid class/id, `{% set classes = [ ‘block-‘ ~ plugin_id|clean_class ] %}`

`without`: if you need to print a render array without specific elements - `{{ content|without(‘links’) }}`, this will print everything in the content variable except `content.links`.


`attach_library`: remember when I said in part one that you could attach a library directly onto a template? This is how we do it! `{{ attach_library(‘stayClassy/slider’) }}`.

`include`: this is used to include some other file or variable within your template, an inline SVG for example! `{{ include(‘path/to/svgimage.svg’) }}`.

Wrap up

Over the course of our tutorial we’ve created our theme, extended the core templates, modified them with our own custom regions, and explored the different ways to access and output the variables accessible to us. Hopefully this has served as a brief primer that gets you up and running with Drupal 8. The new theming system might look scary to you if you’re a bit apprehensive of change, but trust me when I say it’s a fantastic leap forward for the Drupal community. In the third, and final part, we’ll talk about some of the issues we ran into while theming with Twig and Drupal 8. Such as handling regional content, using Twig to our advantage, and taking more control over some of our output.

Read part 3