Template Overrides
New in version 13.1.5
The new Fluid-based rendering architecture allows complete customization of image output via template overrides.
Override the default Fluid templates to customize image rendering output for your site's design requirements.
Table of contents
Overview
The extension provides six Fluid templates for different rendering contexts:
Resources/Private/
├── Templates/Image/
│ ├── Standalone.html # Basic image without wrapper
│ ├── WithCaption.html # Image with <figure>/<figcaption>
│ ├── Link.html # Image wrapped in <a> tag
│ ├── LinkWithCaption.html # Linked image with caption
│ ├── Popup.html # Image with lightbox/popup link
│ └── PopupWithCaption.html # Popup image with caption
└── Partials/Image/
├── Tag.html # <img> element partial
├── TagInFigure.html # <img> without class (for figures)
├── Link.html # <a> wrapper partial
└── Figure.html # <figure> wrapper partial
Note
Partials ship in the standard TYPO3 location
Resources/Private/Partials/Image/ (see
#547).
Templates live in Resources/Private/Templates/Image/ and layouts in
Resources/Private/Templates/Layouts/. When overriding, point your
partialRootPaths at your site package's Resources/Private/Partials/.
Warning
In EXT: paths, use the extension key rte_ckeditor_image
(underscores) — not the Composer package name rte-ckeditor-image
(hyphens). TYPO3 resolves EXT: references by extension key only, so a
hyphenated path silently resolves to nothing and the override is ignored.
Template selection
The
Image automatically selects the appropriate template:
| Condition | Template |
|---|---|
| No link, no caption | Standalone. |
| No link, has caption | With |
| Has link, no popup, no caption | Link. |
| Has link, no popup, has caption | Link |
| Has popup, no caption | Popup. |
| Has popup, has caption | Popup |
Inline vs block rendering
Images are rendered differently depending on whether they appear as block
elements (<figure>) or inline elements (<img> within text flow).
Understanding this distinction is important when overriding templates:
- Block images (
<figure>): - Processed by
renderFigure(). The template handles everything including the link wrapper. UsesLink.,html Link,With Caption. html Popup., orhtml Popup.With Caption. html - Inline images (
<img>in text flow): - Processed by
renderImageAttributes()for the<img>element. The template only renders the<img>tag — alwaysStandalone.. The surroundinghtml <a>wrapper is rebuilt by the defaulttags.atypolink inparseFunc_RTE(resolvest3://URLs, appliesrel="noreferrer", etc.); it is not rendered through a Fluid template. - Popup images:
- Both inline and block use
Popup.orhtml Popupbecause popup attributes (lightbox data, click handler) require special template handling.With Caption. html
| Context | Link | Caption | Handler | Template |
|---|---|---|---|---|
| Block | No | No | renderFigure() | Standalone. |
| Block | No | Yes | renderFigure() | With |
| Block | Yes | No | renderFigure() | Link. |
| Block | Yes | Yes | renderFigure() | Link |
| Block | Popup | No | renderFigure() | Popup. |
| Block | Popup | Yes | renderFigure() | Popup |
| Inline | No | — | renderImageAttributes() | Standalone. |
| Inline | Yes | — | renderImageAttributes() (link rebuilt by default tags.a typolink) | Standalone. |
| Inline | Popup | — | renderImageAttributes() | Popup. |
Setting up overrides
Step 1: Create template directory
In your site package, create the override directory:
mkdir -p packages/my_sitepackage/Resources/Private/Templates/Image/
Step 2: Configure TypoScript
Add the template path to your TypoScript setup:
lib.parseFunc_RTE.tags.img {
# Add your templates with higher priority (higher number = higher priority)
settings.templateRootPaths {
10 = EXT:my_sitepackage/Resources/Private/Templates/
}
settings.partialRootPaths {
10 = EXT:my_sitepackage/Resources/Private/Partials/
}
settings.layoutRootPaths {
10 = EXT:my_sitepackage/Resources/Private/Layouts/
}
}
Note
The configuration must be placed within lib.parseFunc_RTE.tags.img
(not directly in lib.parseFunc_RTE). The same configuration can be
added to externalBlocks.figure.stdWrap for images wrapped in
<figure> blocks (captioned images). Figures are processed via
externalBlocks, not tags.figure — placing the configuration
under tags.figure has no effect. Inline images wrapped in <a>
are rendered by tags.img (recursively, inside the link wrapper), so
they already pick up the configuration defined under tags.img.
Step 3: Create override templates
Copy and modify only the templates you need to customize.
Available DTO properties
All templates receive the image variable containing an
Image:
<!-- Core properties -->
{image.src} <!-- Processed image URL -->
{image.width} <!-- Display width in pixels -->
{image.height} <!-- Display height in pixels -->
{image.alt} <!-- Alternative text -->
{image.title} <!-- Title attribute -->
{image.caption} <!-- Caption text (XSS-sanitized) -->
{image.isMagicImage} <!-- Whether TYPO3 processing applied -->
<!-- HTML attributes -->
{image.htmlAttributes.class} <!-- CSS classes -->
{image.htmlAttributes.style} <!-- Inline styles -->
{image.htmlAttributes.loading} <!-- lazy/eager -->
<!-- Link properties (when linked) -->
{image.link.url} <!-- Link URL -->
{image.link.target} <!-- Link target (_blank, etc.) -->
{image.link.class} <!-- Link CSS classes -->
{image.link.isPopup} <!-- Whether popup/lightbox -->
See ImageRenderingDto for complete property documentation.
Example overrides
Bootstrap 5 responsive image
Override Standalone. for Bootstrap 5 responsive images:
<img src="{image.src}"
alt="{image.alt}"
width="{image.width}"
height="{image.height}"
class="img-fluid {image.htmlAttributes.class}"
{f:if(condition: image.title, then: 'title="{image.title}"')}
{f:if(condition: image.htmlAttributes.style, then: 'style="{image.htmlAttributes.style}"')}
loading="lazy"
decoding="async" />
Figure with custom styling
Override With for custom figure styling:
<figure class="content-image{f:if(condition: image.htmlAttributes.class, then: ' {image.htmlAttributes.class}')}">
<img src="{image.src}"
alt="{image.alt}"
width="{image.width}"
height="{image.height}"
class="content-image__img"
{f:if(condition: image.title, then: 'title="{image.title}"')}
loading="lazy"
decoding="async" />
<figcaption class="content-image__caption">
{image.caption}
</figcaption>
</figure>
PhotoSwipe lightbox integration
Override Popup. for PhotoSwipe v5 integration:
<a href="{image.link.url}"
class="pswp-gallery__item {image.link.class}"
data-pswp-width="{image.width}"
data-pswp-height="{image.height}"
{f:if(condition: image.link.target, then: 'target="{image.link.target}"')}>
<img src="{image.src}"
alt="{image.alt}"
width="{image.width}"
height="{image.height}"
{f:if(condition: image.title, then: 'title="{image.title}"')}
{f:if(condition: image.htmlAttributes.class, then: 'class="{image.htmlAttributes.class}"')}
loading="lazy"
decoding="async" />
</a>
Lazy loading with placeholder
Override Standalone. for progressive image loading:
<img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 {image.width} {image.height}'%3E%3C/svg%3E"
data-src="{image.src}"
alt="{image.alt}"
width="{image.width}"
height="{image.height}"
class="lazyload {image.htmlAttributes.class}"
{f:if(condition: image.title, then: 'title="{image.title}"')}
{f:if(condition: image.htmlAttributes.style, then: 'style="{image.htmlAttributes.style}"')}
decoding="async" />
Best practices
- Only override what you need: Copy only templates requiring changes.
- Preserve accessibility: Always include
altattribute and maintain semantic HTML. - Keep security intact: The DTO properties are pre-sanitized. Do not apply additional encoding that could double-escape content.
- Test all contexts: Verify overrides work with captions, links, and popups.
- Use native lazy loading: Prefer
loading="lazy"over JavaScript solutions. - CSS classes move to figure: When images have captions, CSS classes defined on the
<img>element are applied to the<figure>wrapper instead. This ensures valid HTML5 semantics. If you need classes specifically on the<img>within a figure, create a customWithtemplate override.Caption. html - Decoding attribute: The default templates include
decoding="async"on all images to improve rendering performance by allowing the browser to decode images off the main thread. This is a modern best practice that does not affect visual output. - Whitespace is stripped: The rendering service removes whitespace between HTML tags
to prevent
parseFunc_RTEfrom creating<p> </p>artifacts. Templates can use readable multi-line formatting; it will be normalized. However, deliberate spacing between inline elements will be removed.
Debugging templates
Enable Fluid debugging to inspect available variables:
<f:debug>{_all}</f:debug>
Or in TypoScript:
lib.parseFunc_RTE.settings.debug = 1