Building templates for page types
Much of your work building a SilverStripe site will involve the creation of templates for your own page types. SilverStripe has its own template language. Its basic features like variables, blocks and loops are described in our "templates" reference guide. In this guide, we'll show you specific uses for creating page layouts. This assumes you are familiar with the concept of "page types".
To get a feel for what those templates look like, let's have a look at an abbreviated example. In your webroot, these templates are usually located in
<your-theme> placeholder accordingly, most likely you're using a theme called "simple")
Most of the magic happens in
<html> <head> <% base_tag %> <title>$SiteConfig.Title | $Title</title> $MetaTags(false) </head> <body> <div id="Container"> <header> <h1>Bob's Chicken Shack</h1> </header> <navigation> <% if $Menu(1) %> <ul> <% loop $Menu(1) %> <li><a href="$Link" class="$LinkingMode">$MenuTitle</a></li> <% end_loop %> </ul> <% end_if %> </navigation> <div class="typography"> $Layout </div> </div> </body> </html>
<h2>$Title</h2> $Content $Form
Template inheritance through $Layout
Our example shows two templates, both called
One is located in the
templates/ "root" folder, the other one in a
This "inner template" is used by the
$Layout placeholder in the "root template",
and is inherited based on the underlying PHP classes (read more about template inheritance
on the "page types" topic).
"Layout" is a fixed naming convention, you can't use the same pattern for other folder names.
This variable in the
Layout template contains the main content of the current page,
edited through the WYSIWIG editor in the CMS.
It returns the database content of the
Please note that this database content can be "staged",
meaning that draft content edited in the CMS can be different from published content
shown to your website visitors. In templates, you don't need to worry about this distinction.
$Content variable contain the published content by default,
and only preview draft content if explicitly requested (e.g. by the "preview" feature in the CMS)
(see the "versioning" topic for more details).
<% loop $Menu(1) %>...<% end_loop %>
$Menu(1) is a built-in page control that defines the top-level menu.
You can also create a sub-menu using
$Menu(2), and so forth.
<% loop $Menu(1) %>...<% end_loop %> block defines a repeating element.
It will change the "scope" of your template, which means that all of the template variables you use inside it will refer to a menu item. The template code will be repeated once per menu item, with the scope set to that menu item's page. In this case, a menu item refers to an instance of the
Page class, so you can access all properties defined on there, for example
Note that pages with the
ShowInMenus property set to FALSE will be filtered out
(its a checkbox in the "Settings" panel of the CMS).
<% loop $Children %>...<% end_loop %>
Will loop over all children of the current page context.
Helpful to create page-specific subnavigations.
Most likely, you'll want to use
<% loop $Menu %> for your main menus,
since its independent of the page context.
<% loop $ChildrenOf(<my-page-url>) %>...<% end_loop %>
Will create a list of the children of the given page,
as identified by its
URLSegment value. This can come in handy because its not dependent
on the context of the current page. For example, it would allow you to list all staff member pages
underneath a "staff" holder on any page, regardless if its on the top level or elsewhere.
<% loop $allChildren %>...<% end_loop %>
This will show all children of a page even if the
ShowInMenus property is set to FALSE.
Access to Parent and Level Pages
:::ss <% with $Level(1) %> $Title <% end_with %>
Will return a page in the current path, at the level specified by the numbers.
It is based on the current page context, looking back through its parent pages.
For example, imagine you're on the "bob marley" page, which is three levels in: "about us > staff > bob marley".
$Level(1).Titlewould return "about us"
$Level(2).Titlewould return "staff"
$Level(3).Titlewould return "bob marley"
To simply retrieve the parent page of the current context (if existing), use the
Access to a specific Page
<% with $Page(my-page) %>...<% end_with %>`
"Page" will return a single page from the site tree, looking it up by URL. You can use it in the
<% loop %> format.
Can't be called using
Title and Menu Title
The CMS provides two fields to label a page: "Title" and "Menu Title". "Title" is the title in its full length, while "Menu Title" can be a shorter version suitable for size-constrained menus. If "Menu Title" is left blank by the CMS author, it'll just default to "Title".
Links and Linking Modes
Each menu item we loop over knows its location on the website, so can generate a link to it.
This happens through the SiteTree->Link() method behind the scenes.
We're not using the direct database property
because pages can be nested, so the link needs to be generated on the fly.
In the template syntax, there's no distinction between a method and a property though.
The link is relative by default (see
<% base_tag %>),
you can get an absolute one including the domain through $AbsoluteLink`.
In addition, each menu item gets some context information relative
to the page you're currently viewing, contained in the
By setting a HTML class to this value, you can distinguish the styling of
the currently selected menu item. It can have the following values:
link: You are neither on this page nor in this section.
current: You are currently on this page.
section: The current page is a child of this menu item, so the current "section"
More common uses:
$LinkOrCurrent: Determines if the item is the current page. Returns "link" or "current" strings.
$LinkOrSection: Determines if the item is in the current section, so in the path towards the current page. Useful for menus which you only want to show a second level menu when you are on that page or a child of it. Returns "link" or "section" strings.
InSection(page-url): This if block will pass if we're currently on the page-url page or one of its children.
Example: Only show the menu item linked if its the current one:
<% if $LinkOrCurrent = current %> $Title <% else %> <a href="$Link">$Title</a> <% end_if %>
Breadcrumbs are the path of parent pages which needs to be taken to reach the current page, and can be a great navigation aid for website users.
While you can achieve breadcrumbs through the
<% Level(<level>) %> control already,
there's a nicer shortcut: The
It uses its own template defined in
Simply place a file with the same name in your
folder to customize its output. Here's the default template:
<% if $Pages %> <% loop $Pages %> <% if $Last %>$Title.XML<% else %><a href="$Link">$MenuTitle.XML</a> »<% end_if %> <% end_loop %> <% end_if %>
For more customization options like limiting the amount of breadcrumbs, take a look at SiteTree->Breadcrumbs().
SiteConfig: Global settings
The "SiteConfig" object allows content authors
to modify global data in the CMS, rather than PHP code.
By default, this includes a website title and tagline
(as opposed to the title of a specific page).
It can be extended to hold other data, for example a logo image
which can be uploaded through the CMS.
The object is available to all page templates through the
$MetaTags placeholder in a template returns a segment of HTML appropriate for putting into the
<head> tag. It
will set up title, keywords and description meta-tags, based on the CMS content and is editable in the 'Meta-data' tab
on a per-page basis. If you don’t want to include the title-tag
<title> (for custom templating), use
<title>Title of the Page</title> <meta name="generator" http-equiv="generator" content="SilverStripe 3.0" /> <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
This returns the part of the URL of the page you're currently on.
Shouldn't be used for linking to a page, since the link
is a composite value based on all parent pages as well (through the
Returns the class of the underlying
This can be handy to add to your
<body> tag to influence
In case you want to include parent PHP classes in this list as well,
$CSSClasses placeholder instead.
Returns the base URL for the current site.
This is used to populate the
<base> tag by default.
Can be handy to prefix custom links (not generated through
to ensure they work correctly when the webroot is hosted in a subfolder
rather than its own domain (a common development setup).
Very often, a page will contain some content and a form of some kind. For example, the log-in page has a log-in form. If you are on such a page, the
$Form variable will contain the HTML content of the form. Placing it just below
$Content is a good default. Behind the scenes,
it maps to the
Page_Controller->Form() method. You can add more forms by implementing
new methods there (see "forms" topic for details).
More Advanced Controls
Template variables and controls are just PHP properties and methods on the underlying controllers and model classes. We've just shown you the most common once, in practice you can use any public API on those classes, and extend them with your own. To get an overview on what's available to you, we recommend that you dive into the API docs for the following classes: