Skip to main content

Twig

Twig template architecture

Base.twig

There are a few boilerplate sections that each page needs, such as:
  • meta tags, title and important scripts and styles which live in <head></head>
  • the main div which generally sets the basic layout
  • Secondary scripts and styles which are loaded below the main div
  • <footer></footer> which contains footer links and other global information
These sections should be blocks within a file called base.twig which all pages extend:
{% extends "base.twig" %}

{% block content %}
// Page content goes here
{% endblock %}
If a page needs to customize any of the other sections, then it can include those blocks as well:
{% extends "base.twig" %}

{% block header %}
// Custom header content goes here
{% endblock %}

{% block content %}
// Page content goes here
{% endblock %}

Adding new base files

There may be situations where you need a base file which is very different to the standard base.twig . Instead of hacking it to pieces by extending all the blocks, rather just create a new file, such as base-login.twig or base-ecommerce.twig and extend that in the page template instead

Macros

Documentation link Macros are essentially functions which spit out template partials. You can pass arguments to the macro which will then be available in the template. They help to reduce code re-use and improve readability.
{% macro textarea(name, value, rows = 10, cols = 40) %}
    <textarea name="{{ name }}" rows="{{ rows }}" cols="{{ cols }}">{{ value|e }}</textarea>
{% endmacro %}

Suggested use

Create a macros folder and files to organize related macros:
- macros
	- dates.twig
	- forms.twig
	- images.twig
	- videos.twig
Each of these files when include macros which can be imported into templates. You can either include the whole macro file:
{% import "forms.twig" as forms %}
Or just the specific macros that you need:
{% from 'forms.twig' import input as input_field, textarea %}

Partials

We need some way to break page templates up into smaller pieces to keep them from becoming unwieldy as the site grows. These smaller templates could be thought of as ‘sections’, or ‘components’, but I think the most accurate name is ‘partials’ as they are really just isolated groups of HTML that get pulled into templates. Sections fit the same definition, but a section is the name of a semantic HTML element so that might get a bit confusing.

Creating and including partials

A partial should be linked to a specific page. If its global, its probably better placed as a macro. Therefore to help with search, each partial should start with the name of the page its linked to, followed by an underscore and then the name of the partial, e.g contact_form.twig. The partial should also be stored in a partials folder contained within the page folder. A partial file just contains HTML, it doesn’t need any special Twig syntax. To include the partial, you add the following line wherever you want it rendered:

{% extends "base.twig" %}

{% block content %}
	{% include "/partials/contact-form.twig" %}
{% endblock %}

Embeds

If your partial has slots that can be overwritten, then you can create your partial with blocks:
<div>
	{% block title %}
		<h1>A title</h1>
	{% endblock %}
</div>
Your page template could then just do a regular include as in the above example if it wants to just output the defaults, or it can use the embed keyword to change it:
{% extends "base.twig" %}

{% block content %}
	{% embed 'title_example.twig' %}
		{% block title %}
			    <h1>Edited title</h1>
		{% endblock %}
	{% endembed %}
{% endblock %}

Full folder structure example

- templates/
	- base.twig
	- base-errors.twig
	- errors/
		- 401.twig
		- 404.twig
		- 500.twig
	- macros/
		- dates.twig
		- forms.twig
		- images.twig
		- videos.twig
	- pages/
		- about/
			- about.twig
			- partials/
				- about-header.twig
				- about-history.twig
		-contact/
			- contact.twig
			- partials/
				- contact-form.twig
				- contact-map.twig
		- home/
			- home.twig
			- partials/
				- home-header.twig
				- home-aboutus.twig