In answer to @phil’s question in another thread, here is an explanation on what are grav templates.
I created this thread so the explanation is not lost in that other thread, in case some day it’s useful to someone else browsing the forum. Hope it can be of some use for beginners.
Intro
To customize what grav or it’s theme do more than the settings proposed for tweaking by themes and plugin developpers, one should have a basic understanding of what are HTML, CSS and eventually JS.
There are thousands of websites, tutorials, videos… explaining how to create basic pages with HTML+CSS+JS, and I think that’s a necessary starting point to be able to understand grav templates.
A little reminder of what HTML and CSS do
HTML looks like this:
<div id="some-id">
<span class="some-class">
<h1>Phil</h1>
<img src="https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.getgrav.org/phil/96/7554_2.png">
</span>
</div>
This means I have a title (h1) and and image (img) elements which are in a span container element, which is itself in a div element.
Notice all the <something> and </something> start and end tags?
This is how it looks:
Now if I want to style this, I’ll use CSS:
#some-id {
background-color: red;
}
.some-class {
color: blue;
}
.some-class > h1 {
text-align: center;
}
img {
width: 500px;
}
This will color the background of my div container red.
The span will be in that container, so I’ll have blue text on the red background.
The title (h1) will inherit the color of it’s parent, so will be blue, and will be centered.
The image (img) will have 500 pixels width.
In this case only the h1 title inside elements with the some-class class will be centered.
So if I have other h1 titles I would like to center, I can change this par of my CSS from:
.some-class > h1 {
text-align: center;
}
to
h1 {
text-align: center;
}
Now the templates
Ok so what are templates?
Well templates are a way to extend HTML. It’s an additional syntax that lets grav build HTML from different pieces of code. So you don’t have to write HTML yourself.
Grav templates use the twig syntax which is recognizable from it’s use of curly brackets: {% something %} and {{ something }}.
Now to use our previous example in some pages, we could create the following templates in our theme:
templates/example.html.twig:
<html>
<head>
{% block stylesheets %}
{% do assets.addCss('theme://css/example.css) %}
{% endblock %}
</head>
<body>
{% include 'partials/image_on_red_background.html.twig' with { image_title: page.header.title, image_url: page.header.image } %}
{% block content %}{% endblock %}
</body>
</html>
templates/partials/image_on_red_background.html.twig:
<div id="some-id">
<span class="some-class">
<h1>{{ image_title }}</h1>
<img src="{{ image_url }}">
</span>
</div>
css/example.css:
#some-id {
background-color: red;
}
.some-class {
color: blue;
}
.some-class > h1 {
text-align: center;
}
img {
width: 500px;
}
Now we can create a new page, choose the example template in the grav admin (or markdown header) with the following content (to customize the frontmatter in text mode (what’s here between the --- ---) in grav admin you need to choose “expert” mode):
---
template: example
title: Phil
image: https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.getgrav.org/phil/96/7554_2.png
---
This text will be displayed under the title and image.
Your page, when saved will look like this:
This is an extremely simplified example of how templates work.
But in short, one can create as many templates as they want, they can include them in one another. Templates make it easy to build blocks that can be used and reused in different context to create pages from these blocks. For example a menu can be a block included in many different pages, or one can make a feed block…
Tweaking templates to make them do what one wants is fairly easy when one understands the basics of HTML and CSS, the grav and twig docs explain pretty well the specifics of the template syntax.
Once you get into it, the risk is that starting from little tweaks on an existing theme you end up liking it and creating you own theme ![]()


