Assets (CSS, JavaScript, Media)

The TYPO3 component responsible for rendering the HTML and adding assets to a TYPO3 frontend or backend page is called PageRenderer.

The PageRenderer collects all assets to be rendered, takes care of options such as concatenation or compression and finally generates the necessary tags.

There are multiple ways to add assets to the PageRenderer in TYPO3. For configuration options via TypoScript (usually used for the main theme files), see the TypoScript Reference. In extensions, both directly using the PageRenderer as well as using the more convenient AssetCollector is possible.


The AssetCollector is available since TYPO3 10.3.


The AssetCollector is a concept to allow custom CSS/JS code, inline or external, to be added multiple times in e.g. a Fluid template (via <f:asset.script> or <f:asset.css> Viewhelpers) but rendered only once in the output.

The priority flag (default: false) controls where the asset is included:

  • JavaScript will be output inside <head> if $priority == true or at the bottom of the <body> tag if $priority == false.
  • CSS will always be output inside <head>, yet grouped by $priority.

The AssetCollector helps to work with content elements as components, effectively reducing the CSS to be loaded. It leverages making use of HTTP/2 which removes the necessity to have all files concatenated into one file.

The AssetCollector class is implemented as a singleton (SingletonInterface). It replaces various other existing options in TypoScript and methods in PHP to insert Javascript code and CSS data.

Former methods:

use TYPO3\CMS\Core\Page\PageRenderer;
use TYPO3\CMS\Core\Utility\GeneralUtility;

$pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
  • $GLOBALS['TSFE']->additionalHeaderData[$name] = $javascriptcode;
  • $GLOBALS['TSFE']->setJS($name, $javascriptcode)
  • $pageRenderer->addHeaderData($javascriptcode)
  • $pageRenderer->addCssFile($file)
  • $pageRenderer->addCssInlineBlock($name, $csscode)
  • $pageRenderer->addCssLibrary($file)
  • $pageRenderer->addJsFile($file)
  • $pageRenderer->addJsFooterFile($file)
  • $pageRenderer->addJsFooterLibrary($name, $file)
  • $pageRenderer->addJsFooterInlineCode($name, $javascriptcode)
  • $pageRenderer->addJsInlineCode($name, $javascriptcode)
  • $pageRenderer->addJsLibrary($name, $file)

The AssetCollector also collects information about “imagesOnPage”, which can be used in cached and non-cached components.


  • \TYPO3\CMS\Core\Page\AssetCollector::addJavaScript(string $identifier, string $source, array $attributes, array $options = []): self
  • \TYPO3\CMS\Core\Page\AssetCollector::addInlineJavaScript(string $identifier, string $source, array $attributes, array $options = []): self
  • \TYPO3\CMS\Core\Page\AssetCollector::addStyleSheet(string $identifier, string $source, array $attributes, array $options = []): self
  • \TYPO3\CMS\Core\Page\AssetCollector::addInlineStyleSheet(string $identifier, string $source, array $attributes, array $options = []): self
  • \TYPO3\CMS\Core\Page\AssetCollector::addMedia(string $fileName, array $additionalInformation): self
  • \TYPO3\CMS\Core\Page\AssetCollector::removeJavaScript(string $identifier): self
  • \TYPO3\CMS\Core\Page\AssetCollector::removeInlineJavaScript(string $identifier): self
  • \TYPO3\CMS\Core\Page\AssetCollector::removeStyleSheet(string $identifier): self
  • \TYPO3\CMS\Core\Page\AssetCollector::removeInlineStyleSheet(string $identifier): self
  • \TYPO3\CMS\Core\Page\AssetCollector::removeMedia(string $identifier): self
  • \TYPO3\CMS\Core\Page\AssetCollector::getJavaScripts(?bool $priority = null): array
  • \TYPO3\CMS\Core\Page\AssetCollector::getInlineJavaScripts(?bool $priority = null): array
  • \TYPO3\CMS\Core\Page\AssetCollector::getStyleSheets(?bool $priority = null): array
  • \TYPO3\CMS\Core\Page\AssetCollector::getInlineStyleSheets(?bool $priority = null): array
  • \TYPO3\CMS\Core\Page\AssetCollector::getMedia(): array


If the same asset is registered multiple times using different attributes or options, both sets are merged. If the same attributes or options are given with different values, those registered last will overwrite the existing ones.


There are also two Viewhelpers, the f:asset.css and the f:asset.script Viewhelper which use the AssetCollector API.

Rendering order

Currently, CSS and JavaScript registered with the AssetCollector will be rendered after their PageRenderer counterparts. The order is:

  • <head>
  • page.includeJSLibs.forceOnTop
  • page.includeJSLibs
  • page.includeJS.forceOnTop
  • page.includeJS
  • AssetCollector::addJavaScript() with ‘priority’
  • page.jsInline
  • AssetCollector::addInlineJavaScript() with ‘priority’
  • </head>
  • page.includeJSFooterlibs.forceOnTop
  • page.includeJSFooterlibs
  • page.includeJSFooter.forceOnTop
  • page.includeJSFooter
  • AssetCollector::addJavaScript()
  • page.jsFooterInline
  • AssetCollector::addInlineJavaScript()


JavaScript registered with AssetCollector is not affected by config.moveJsFromHeaderToFooter.


Add a JavaScript file to the collector with script attribute data-foo="bar":

   ->addJavaScript('my_ext_foo', 'EXT:my_ext/Resources/Public/JavaScript/foo.js', ['data-foo' => 'bar']);

Add a JavaScript file to the collector with script attribute data-foo="bar" and priority which means rendering before other script tags:

   ->addJavaScript('my_ext_foo', 'EXT:my_ext/Resources/Public/JavaScript/foo.js', ['data-foo' => 'bar'], ['priority' => true]);

Add a JavaScript file to the collector with type="module" (by default, no type= is output for JavaScript):

   ->addJavaScript('my_ext_foo', 'EXT:my_ext/Resources/Public/JavaScript/foo.js', ['type' => 'module']);


There are two events available that allow additional adjusting of assets: