Asset Management
When building a site, administrator and developers can add CSS and JavaScript assets to their site via Contao’s page layouts. However, as an application or extension developer, you might want to add your own assets to a page, whenever necessary.
Global Arrays
Contao utilises global arrays to store references for later inclusion into the page layout.
Array | Description |
---|---|
$GLOBALS['TL_BODY'] | Contains HTML code to be included before </body> . |
$GLOBALS['TL_CSS'] | Contains relative or absolute paths to CSS assets to be included in the <head> of the document. |
$GLOBALS['TL_HEAD'] | Contains HTML code to be included in the <head> of the document. |
$GLOBALS['TL_JAVASCRIPT'] | Contains relative or absolute paths to JavaScripts assets to be included in the <head> of the document. |
$GLOBALS['TL_MOOTOOLS'] | Contains HTML code to be included before </body> . |
Note
In the back end, only TL_CSS
, TL_JAVASCRIPT
and TL_MOOTOOLS
will work.
Adding CSS & JavaScript Assets
In order to add a new CSS or JavaScript file for the <head>
to the document, add
a new entry to the $GLOBALS['TL_CSS']
or $GLOBALS['TL_JAVASCRIPT']
array respectively,
for example in your content element or front end module.
The entry can contain a path relative to the Contao installation directory, or an
absolute path for an external asset.
$GLOBALS['TL_CSS'][] = 'bundles/myextension/frontend.css';
$GLOBALS['TL_JAVASCRIPT'][] = 'bundles/myextension/scripts.js';
Options
Contao allows a few options to be set for each file. These options are appended
to the file path and separated by a pipe |
character.
Option | Example | Description |
---|---|---|
Static | |static | Defines the asset as “static”. |
Media | |print | Defines the media attribute of the <link> tag (CSS only). |
Async | |async | Defines the async attribute of the <script> tag (JavaScript only). |
Version | |1 | Appends a ?v=… parameter. Can be a version number or also a timestamp. |
All options can be combined in no particular order.
$GLOBALS['TL_CSS'][] = 'files/theme/css/print.css|print|static|1';
$GLOBALS['TL_JAVASCRIPT'][] = 'bundles/myextension/scripts.js|2|async|static';
Static
By appending |static
you can define the asset as being “static”, meaning that
it can be combined with other static assets into one file (if enabled in Contao’s
page layout). Without the static
option, the stylesheet is always included separately.
A stylesheet should be defined as static
, if it will occur on every or most pages
of a website, as it is more advantageous then for it to be combined with other static
assets.
$GLOBALS['TL_CSS'][] = 'bundles/myextension/frontend.css|static';
$GLOBALS['TL_JAVASCRIPT'][] = 'bundles/myextension/scripts.js|static';
Media
In case of stylesheets, you can also define its media property the same ways as
defining it as “static”. For instance, if a stylesheet is only to be included for
the print
media, append |print
to the stylesheet path.
$GLOBALS['TL_CSS'][] = 'files/theme/css/print.css|print';
This results in the following HTML code in the front end:
<link rel="stylesheet" href="files/theme/css/print.css" media="print">
Async
You can load JavaScript assets asynchronously by adding the option |async
, which
enables the async
attribute of the <script>
tag:
$GLOBALS['TL_JAVASCRIPT'][] = 'bundles/myextension/scripts.js|async';
When using both the async
and static
option and combining is enabled in the
page layout, all JavaScript assets that are static
and async
will be combined
into one file.
Version
This option is used for cache busting, to ensure that clients receive the latest version of the asset, when it changes. It can either be a simple version number or also an automated timestamp.
$cssTimestamp = filemtime($this->rootDir.'/bundles/myextension/frontend.css');
$GLOBALS['TL_CSS'][] = 'bundles/myextension/frontend.css|'.$cssTimestamp;
$jsTimestamp = filemtime($this->rootDir.'/bundles/myextension/scripts.js');
$GLOBALS['TL_JAVASCRIPT'][] = 'bundles/myextension/scripts.js|'.$jsTimestamp;
Generating Style and Script Tags
As mentioned in the introduction, it is also possible to add custom HTML to either
the <head>
or the end of the <body>
element. Often this is used to add assets
manually, by adding the apropriate <link>
, <style>
or <script>
HTML tags.
Contao offers a few static utility functions for this purpose via the \Contao\Template
class.
Template::generateStyleTag($href, $media, $mtime)
This returns a <link rel="stylesheet" …>
tag and takes three arguments: the
path to the stylesheet (absolute or relative to the base), an optional media
attribute and an optional modification time, which Contao will use to append a
query parameter to the file for cache busting. The latter can also be set to
null
in order to automatically use the file’s modification time for cache busting
(if it is a relative file path).
$GLOBALS['TL_HEAD'][] = \Contao\Template::generateStyleTag('bundles/myextension/print.css', 'print', null);
Template::generateInlineStyle($script)
This wraps the given CSS with <style>…</style>
.
$GLOBALS['TL_HEAD'][] = \Contao\Template::generateInlineStyle($this->generateCss());
Template::generateScriptTag(…)
This returns a <script src="…" …>
tag and takes six arguments:
$href
: the path to the script (absolute or relative to the base)$async
: whether theasync
attribute should be added to the tag (defaultfalse
)$mtime
: an optional modification time, which Contao will use to append a query parameter to the file for cache busting. This can also be set tonull
in order to automatically use the file’s modification time for cache busting.$hash
: optional hash for anintegrity
attribute.$crossorigin
: optionalcrossorigin
attribute.$referrerpolicy
: optionalreferrerpolicy
attribute.
Info
Some of these parameters are only available in newer Contao versions.
$GLOBALS['TL_BODY'][] = \Contao\Template::generateScriptTag('bundles/myextension/scripts.js', false, null);
Template::generateInlineScript($script)
This wraps the given JavaScript with <script>…</script>
.
$GLOBALS['TL_BODY'][] = \Contao\Template::generateInlineScript($this->generateJavaScript());
Template::generateFeedTag($href, $format, $title)
This generates a <link type="application/…" rel="alternate" href="…" title="…">
tag for RSS feeds. It takes three arguments: the URL to the feed, its format and
the title of the feed.
$GLOBALS['TL_HEAD'][] = \Contao\Template::generateFeedTag('share/myfeed.xml', 'rss', 'My Feed');
Twig
While you cannot directly add assets to the aforementioned globals in Twig templates, you can use the
add
tag to add styles and JavaScripts to different sections of the document.
Contao also comes with a _stylesheet
component which helps you render inline style sheets:
{% use "@Contao/component/_stylesheet.html.twig" %}
{# Renders `<link rel="stylesheet" href="…"> #}
{% with {file: asset('styles.css')} %}
{{ block('stylesheet_component') }}
{% endwith %}
You can also lazy-load a stylesheet:
{% use "@Contao/component/_stylesheet.html.twig" %}
{% with {file: asset('styles.css'), lazy: true} %}
{{ block('stylesheet_component') }}
{% endwith %}
This will render:
<link rel="preload" as="style" href="…" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="…"></noscript>
Using Contao’s add
tag you can output styles and JavaScripts in different sections of the
document.
Accessing Assets in Templates
Info
This feature is available in Contao 4.5 and later.
Contao also provides the possibility to access assets via the Symfony Asset Component. It automatically registers assets from packages and these assets are grouped by their “package”. Each package can have a different version strategy. These assets can then be accessed within Contao Templates in several ways:
- Via the
asset(…)
Twig function in Twig templates. - Via the
$this->asset(…)
helper function in legacy PHP templates. - Via the
{{asset::*::*}}
insert tag, wherever supported.
These methods are basically shortcuts to the asset component of the Symfony framework, so Contao supports whatever Symfony Assets supports. The methods take two arguments: the path or name of the asset within the package, and the package name.
<script src="<?= $this->asset('foobar.js', 'fooexample') ?>"></script>
<script src="<?= $this->asset('js/tablesort.min.js', 'contao-components/tablesort') ?>"></script>
<script src="{{asset::jquery.js::contao-components/jquery}}"></script>
There are several use cases of using the asset helper within Contao:
Packages of type
contao-components
are registered by their package name. Therefore, one can include the (imaginary) file inassets/jquery/jquery.js
through{{asset::jquery.js::contao-components/jquery}}
. It uses the package version to generate a strategy that adds unique file names, so the resulting path forcontao-components/jquery: 1.1.0
will beassets/jquery/jquery.js?v=1.1.0
.If a bundle has a
public/
folder (or its deprecated siblingsrc/Resources/public/
), that folder is registered as an asset through the lowercase bundle short name. A file of aFooExampleBundle
invendor/foo/example/src/Resources/public/foobar.min.js
is symlinked by Symfony toweb/bundles/fooexample/foobar.min.js
(regardless of the asset component).- By default, a bundle does not have a version, so no version suffix is added.
The asset component resolves
{{asset::foobar.min.js::foo_example}}
toweb/bundles/fooexample/foobar.min.js
. - If the
public
folder has amanifest.json
in its root, that file is used to generate a manifest.json version strategy. For{{asset::foobar.js::foo_example}}
the asset component will look upfoobar.js
in themanifest.json
and output that path. This is useful when using e.g. Webpack Encore to generate the assets, as hashed file names are resolved toweb/bundles/fooexample/foobar-1ussdg71.js
.
- By default, a bundle does not have a version, so no version suffix is added.
The asset component resolves