A site template
A template is an extension that defines the overall page markup: where the header is, where the main content goes, where the column with modules sits. The component and the modules output only their own fragments, and the template assembles a whole HTML page from them.
Where it lives
Site templates are stored in the templates folder, panel templates in administrator/templates. Create a minimal template by hand:
templates/mytheme/
├── templateDetails.xml the manifest
├── index.php the page markup
└── html/ layout overrides
media/templates/site/mytheme/
└── css/
└── template.css stylesThe manifest
<?xml version="1.0" encoding="UTF-8"?>
<!-- templates/mytheme/templateDetails.xml -->
<extension type="template" client="site" method="upgrade">
<name>mytheme</name>
<version>1.0.0</version>
<description>A learning template</description>
<files>
<filename>index.php</filename>
<filename>templateDetails.xml</filename>
<folder>html</folder>
</files>
<media destination="templates/site/mytheme" folder="media">
<folder>css</folder>
</media>
<positions>
<position>menu</position>
<position>sidebar</position>
<position>footer</position>
</positions>
</extension>The positions section lists the positions: these are the names the administrator sees in the Position list when configuring a module.
The index.php file
<?php
// templates/mytheme/index.php
defined('_JEXEC') or die;
$this->getWebAssetManager()->registerAndUseStyle('template.mytheme', 'template.css');
?>
<!DOCTYPE html>
<html lang="<?php echo $this->language; ?>" dir="<?php echo $this->direction; ?>">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<jdoc:include type="metas" />
<jdoc:include type="styles" />
<jdoc:include type="scripts" />
</head>
<body>
<header>
<jdoc:include type="modules" name="menu" style="none" />
</header>
<main>
<jdoc:include type="message" />
<jdoc:include type="component" />
</main>
<?php if ($this->countModules('sidebar')) : ?>
<aside>
<jdoc:include type="modules" name="sidebar" style="html5" />
</aside>
<?php endif; ?>
<footer>
<jdoc:include type="modules" name="footer" style="none" />
</footer>
</body>
</html>In a template $this is the document object. The jdoc:include tags are the places where Joomla inserts ready parts of the page.
The jdoc:include tags
| Tag | What it inserts |
|---|---|
type="metas" | The page title and meta tags |
type="styles", type="scripts" | Styles and scripts from the asset manager |
type="component" | The component output — the main content |
type="message" | System messages such as "Item saved" |
type="modules" name="sidebar" | All modules of the sidebar position |
The style attribute picks the module wrapper: none prints the module as is, html5 adds a block with the module title. The countModules() method returns the number of modules in a position — this way an empty column is not printed at all.
Styles
/* media/templates/site/mytheme/css/template.css */
body {
max-width: 960px;
margin: 0 auto;
font-family: sans-serif;
}Joomla looks for the bare name template.css in the css folder of the active template inside media/templates/site.
Installing and seeing the result
- System → Install → Discover → install
mytheme. - System → Site Template Styles → tick
mythemeand press Default. - Give the
mod_hellomodule thesidebarposition and the main menu module themenuposition.
Open the site: the Cassiopeia look is gone and the page is built from your markup — the menu on top, the content, the greeting block in the column.
A child template
Writing a template from scratch is rarely needed. More often you take a ready one and change a few files in it. Child templates exist for that: System → Site Templates → Cassiopeia, the Create Child Template button. Joomla creates a folder such as templates/cassiopeia_mychild whose manifest names the parent in the parent tag. A child template takes every file from its parent except those it contains itself: that is where you put your own styles and layout overrides from the html folder. Updating Cassiopeia does not touch them.
Common mistake
The jdoc:include type="message" tag is forgotten in index.php. The site works, but messages — "Wrong password", "Form submitted" — never appear, and the visitor does not understand what happened. This tag is mandatory in every template.