Templating
Templates are inherited, so if you call a template that isn't defined in your theme but exist in a parent theme, the parent template will be loaded.
Each theme defines a templates folder in its getTemplatesFolder()
method which is relative to the theme base path. By default this equals
to templates
.
Layouts in Pro version
You can set any templates to your category groups and sections, if a
layout matches for that request, the layout associated will be added to
the variables. In your template you simply need to call {{ layout.renderRegions() }}
. The view mode for such a request is
always the default one.
For convenience a default page template is defined in this plugin : themed_page
, see here, this template could be used in every section/category, and can be overridden.
There are two ways to render layouts: regions or displays. The method Layout::render(Element $element, string $viewMode)
will render the
displays, the other Layout::renderRegions()
the regions.
Rendering the regions will call a special template defined by the
theme in ThemePlugin::getRegionsTemplate()
, by default this equals to regions
.
Template naming (Pro)
Each element of the page (layouts, regions, blocks, field and file displayers) templates can be overridden by your themes using a specific folder structure that allows much granularity. These folder structures are defined below, they are ordered from most to less specific where the most specific will be loaded first if found.
The following variables mentioned in folder structures are defined as :
-
{type}
: The layout type,user
,tag
,category
,global
,entry
,product
,variant
,volume
orcustom
-
{viewMode}
: The rendered view mode's handle
Entry layouts
Entry layouts will define more templates as
they define two keys, {section}
the handle of the section, and {entryType}
the handle of the entry type.
Rendering layouts (displays mode):
layouts/{type}_{section}-{entryType}_{viewMode}.twig layouts/{type}_{section}_{viewMode}.twig layouts/{type}_{section}-{entryType}.twig layouts/{type}_{section}.twig layouts/{type}.twig layouts/layout.twig
Rendering regions:
regions/{type}_{section}-{entryType}_region-{handle}.twig regions/{type}_{section}_region-{handle}.twig regions/{type}_{section}-{entryType}_region.twig regions/{type}_{section}_region.twig regions/{type}_region-{handle}.twig regions/{type}_region.twig regions/region-{handle}.twig regions/region.twig
Where {handle}
is the region's handle
blocks/{type}_{section}-{entryType}_{region}_{handle}.twig blocks/{type}_{section}_{region}_{handle}.twig blocks/{type}_{section}-{entryType}_{handle}.twig blocks/{type}_{section}_{handle}.twig blocks/{type}_{handle}.twig blocks/{handle}.twig
Where {handle}
is the machine name of the block. A block latestBlogs
of a provider system
will be system-latestBlogs
Where {region}
is the handle of the region the block is in.
Rendering fields:
fields/{type}_{section}-{entryType}_{viewMode}_{displayer}_{field}.twig fields/{type}_{section}_{viewMode}_{displayer}_{field}.twig fields/{type}_{section}-{entryType}_{viewMode}_{displayer}.twig fields/{type}_{section}_{viewMode}_{displayer}.twig fields/{type}_{section}-{entryType}_{displayer}_{field}.twig fields/{type}_{section}_{displayer}_{field}.twig fields/{type}_{section}-{entryType}_{displayer}.twig fields/{type}_{section}_{displayer}.twig fields/{type}_{displayer}_{field}.twig fields/{type}_{displayer}.twig fields/{displayer}_{field}.twig fields/{displayer}.twig
Where {displayer}
is the handle of the field displayer.
Where {field}
is the handle of the field.
Rendering files:
files/{type}_{section}-{entryType}_{viewMode}_{displayer}_{field}.twig files/{type}_{section}_{viewMode}_{displayer}_{field}.twig files/{type}_{section}-{entryType}_{viewMode}_{displayer}.twig files/{type}_{section}_{viewMode}_{displayer}.twig files/{type}_{section}-{entryType}_{displayer}_{field}.twig files/{type}_{section}_{displayer}_{field}.twig files/{type}_{section}-{entryType}_{displayer}.twig files/{type}_{section}_{displayer}.twig files/{type}_{displayer}_{field}.twig files/{type}_{displayer}.twig files/{displayer}_{field}.twig files/{displayer}.twig
Where {displayer}
is the handle of the file displayer.
Where {field}
is the handle of the field.
Rendering groups:
groups/{type}_{section}-{entryType}_{viewMode}_group-{handle}.twig groups/{type}_{section}_{viewMode}_group-{handle}.twig groups/{type}_{section}-{entryType}_{viewMode}_group.twig groups/{type}_{section}_{viewMode}_group.twig groups/{type}_{section}-{entryType}_group-{handle}.twig groups/{type}_{section}_group-{handle}.twig groups/{type}_{section}-{entryType}_group.twig groups/{type}_{section}_group.twig groups/{type}_group-{handle}.twig groups/{type}_group.twig groups/group-{handle}.twig groups/group.twig
Where {handle}
is the group's handle.
All other layouts
The mentionned key
variable is defined as such :
- For a user:
user
- For a category/volume/tag/global/product layout it will be the handle of the associated category group/volume/tag group/global set/product type
- For a custom layout, the handle of the layout
Rendering layouts (displays mode):
layouts/{type}_{key}_{viewMode}.twig layouts/{type}_{key}.twig layouts/{type}.twig layouts/layout.twig
Rendering regions:
regions/{type}_{key}_region-{handle}.twig regions/{type}_{key}_region.twig regions/{type}_region-{handle}.twig regions/{type}_region.twig regions/region-{handle}.twig regions/region.twig
Where {handle}
is the region's handle
Rendering blocks:
blocks/{type}_{key}_{region}_{handle}.twig blocks/{type}_{key}_{handle}.twig blocks/{type}_{handle}.twig blocks/{handle}.twig
Where {handle}
is the machine name of the block. A block latestBlogs
of a provider system
will be system-latestBlogs
Where {region}
is the handle of the region the block is in
Rendering fields:
fields/{type}_{key}_{viewMode}_{displayer}_{field}.twig fields/{type}_{key}_{viewMode}_{displayer}.twig fields/{type}_{key}_{displayer}_{field}.twig fields/{type}_{key}_{displayer}.twig fields/{type}_{displayer}_{field}.twig fields/{type}_{displayer}.twig fields/{displayer}_{field}.twig fields/{displayer}.twig
Where {displayer}
is the handle of the field displayer.
Where {field}
is the handle of the field.
Rendering files:
files/{type}_{key}_{viewMode}_{displayer}_{field}.twig files/{type}_{key}_{viewMode}_{displayer}.twig files/{type}_{key}_{displayer}_{field}.twig files/{type}_{key}_{displayer}.twig files/{type}_{displayer}_{field}.twig files/{type}_{displayer}.twig files/{displayer}_{field}.twig files/{displayer}.twig
Where {displayer}
is the handle of the file displayer.
Where {field}
is the handle of the field.
Rendering groups:
groups/{type}_{key}_{viewMode}_group-{handle}.twig groups/{type}_{key}_{viewMode}_group.twig groups/{type}_{key}_group-{handle}.twig groups/{type}_{key}_group.twig groups/{type}_group-{handle}.twig groups/{type}_group.twig groups/group-{handle}.twig groups/group.twig
Where {handle}
is the group's handle.
Global variables & tests
Available variables :
craft.themes.layouts
: Layouts service
craft.themes.viewModes
: View mode service
craft.themes.registry
: Theme registry
craft.themes.view
: Theme view service
craft.themes.current
: Current theme
Tests :
Array test : {% if variable is array %}
Numeric test : {% if variable is numeric %}
Instance of test : {% if variable is instanceof "My\\Namespaced\\Class" %}
Events (Pro)
More templates and variables can be defined by listening to events on the ViewService
class :
- Layouts : event
BEFORE_RENDERING_LAYOUT
- Files : event
BEFORE_RENDERING_FILE
- Fields : event
BEFORE_RENDERING_FIELD
- Blocks : event
BEFORE_RENDERING_BLOCK
- Regions : event
BEFORE_RENDERING_REGION
- Groups : event
BEFORE_RENDERING_GROUP
Example :
Event::on( ViewService::class, ViewService::BEFORE_RENDERING_FILE, function (RenderEvent $event) { $event->prependTemplate('myTemplate') ->addVariable('myVar', 'myValue'); });
Those events can also be used to modify elements's classes and attributes :
Event::on( ViewService::class, ViewService::BEFORE_RENDERING_FILE, function (RenderEvent $event) { $e->variables['classes']->add(['my-class', 'my-other-class']); $e->variables['attributes']->add('id', 'my-id'); $e->variables['containerClasses']->add('container-class'); $e->variables['containerAttributes']->add('id', 'container-id'); $e->variables['labelClasses']->remove('label-class'); $e->variables['labelAttributes']->remove('label-id'); });
Or to skip the rendering of any element :
Event::on( ViewService::class, ViewService::BEFORE_RENDERING_FILE, function (RenderEvent $event) { $event->render = false; });
Root templates folder
It is recommended to not use the root templates
folder when using themes, if some templates are defined both in this
folder and in a theme, the root templates folder will take precedence.
Other plugins templates
A theme can't override templates that have a namespace (ie other plugin templates), unless they register their templates roots with the '' (empty string) key.