Are you looking for tips & tricks to implement TYPO3 responsive images? To make your TYPO3 site modern responsive way - In this article, you will find 10+ possible ways to create responsive images using TYPO3 core and third-party TYPO3 extensions. Let’s see how!
TYPO3 is a well known OpenSource CMS due to it’s almost 10K+ features within TYPO3 core ;) Example, TYPO3 supports backend crop and resize features since 2016. The core TYPO3 team and community is always eager to add modern features to their lovable CMS to make life better for the editor, integrator and developer.
Of course, TYPO3 responsive design and images are the common practice to support images for multiple devices. Here, you will find many of the well-known techniques, but I’ve prepared all possible techniques to efficiently implement TYPO3 responsive images.
1. TYPO3 core Fluid ViewHelper <f:media />
Let’s initiate this topic with TYPO3 core’s classic ViewHelper call <f:media />.
<!-- TYPO3 core example -->
typo3/sysext/fluid_styled_content/Resources/Private/Partials/Media/Rendering/Image.html
<!-- Syntax of <f:media /> -->
<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" data-namespace-typo3-fluid="true">
<f:media
class="image-embed-item"
file="{file}"
width="{dimensions.width}"
height="{dimensions.height}"
alt="{file.alternative}"
title="{file.title}"
loading="{settings.media.lazyLoading}"
/>
</html>
<!-- OUTPUT -->
<div id="c1" class="frame frame-default frame-type-image frame-layout-0">
<div class="ce-image ce-center ce-above">
<div class="ce-gallery" data-ce-columns="1" data-ce-images="1">
<div class="ce-outer">
<div class="ce-inner">
<div class="ce-row">
<div class="ce-column">
<figure class="image">
<img class="image-embed-item" title="Title Text" alt="Alt Text" src="/fileadmin/_processed_/6/e/csm_image_02_38sd8s8776.jpg" loading="lazy" width="600" height="337">
</figure>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
Tips:
Since TYPO3 10.x support browser native lazyload support using TypoScript constant {settings.media.lazyLoading}
Override EXT.fluid_styled_content
To extend or override TYPO3 core’s EXT.fluid_styled_content, you can override the fluid using below TypoScript.
styles {
templates {
layoutRootPath = EXT:yourtemplate/Resources/Private/Layouts/ContentElements/
partialRootPath = EXT:yourtemplate/Resources/Private/Partials/ContentElements/
templateRootPath = EXT:yourtemplate/Resources/Private/Templates/ContentElements/
}
}
TYPO3 crop feature since 8.7
I know you already knows this feature well, But if you are newbie in TYPO3 then highly recommend to read official TYPO3 documentation - View Document
2. Using <img srcset /> Attribute
One of the most popular ways to integrate TYPO3 responsive images using <img /> tag’s “srcset” attribute. Here is the sample code snippet.
<!-- Syntax of srcset using additionalAttributes → <f:media class="image-embed-item" file="{file}" width="{dimensions.width}" height="{dimensions.height}" alt="{file.alternative}" title="{file.title}" loading="{settings.media.lazyLoading}" additionalAttributes="{srcset: '{f:uri.image(image: file, maxWidth: 768)} 768w, {f:uri.image(image: file, maxWidth: 990)} 990w, {f:uri.image(image: file, maxWidth: 1200)} 1200w, {f:uri.image(image: file, maxWidth: 1440)} 1440w, {f:uri.image(image: file, maxWidth: 1900)} 1900w', sizes: '(min-width: 1200px) 50vw, 100vw'}" />
<!-- OUTPUT --> <img srcset="/fileadmin/_processed_/6/e/csm_image_01_8159d1e3b0.jpg 768w, /fileadmin/_processed_/6/e/csm_image_01_19d1039365.jpg 990w, /fileadmin/_processed_/6/e/csm_image_01_9cee8957cf.jpg 1200w, /fileadmin/_processed_/6/e/csm_image_01_922756210c.jpg 1440w, /fileadmin/_processed_/6/e/csm_image_01_0e137c815f.jpg 1900w" sizes="(min-width: 1200px) 50vw, 100vw" class="image-embed-item" title="Title Text" alt="Alt Text" src="/fileadmin/_processed_/6/e/csm_image_02_38sd8s8776.jpg" loading="lazy" width="600" height="337" >
Tips
You can configure width and height settings from TypoScript constant.
styles.content.textmedia.maxW
styles.content.textmedia.maxWInText
3. Using <img data-srcset /> Attribute
Some of the TYPO3 integrators prefer `data-srcset` to integrate TYPO3 responsive images, Checkout how.
<img
class="image-embed-item lazy"
data-src="{f:uri.image(image: file, treatIdAsReference: 1, maxWidth: 1168)}"
data-srcset="{f:uri.image(image: file, treatIdAsReference: 1, maxWidth: 768)} 768w,
{f:uri.image(image: file, treatIdAsReference: 1, maxWidth: 990)} 990w,
{f:uri.image(image: file, treatIdAsReference: 1, maxWidth: 1200)} 1200w,
{f:uri.image(image: file, treatIdAsReference: 1, maxWidth: 1440)} 1440w,
{f:uri.image(image: file, treatIdAsReference: 1, maxWidth: 1900)} 1900w"
data-sizes="(min-width: 1200px) 1168px, 100vw"
alt="{file.alternative}"
title="{file.title}"
width="{dimensions.width}"
height="{dimensions.height}"
/>
4. Using <picture /> Tag
One of my favorite ways to integrate TYPO3 responsive images is using <picture /> tag because there are cool JavaScript libraries available to integrate in a better way.
<picture>
<source
media="(min-width: 990px)"
srcset="{f:uri.image(image: file, maxWidth: 1200)}"
/>
<source srcset="{f:uri.image(image: file, maxWidth: 768)}" />
<img src="{f:uri.image(image: file, maxWidth: 768)}" alt="{file.alternative}" />
</picture>
5. Using TypoScript SourceCollection
Yeah! Sometimes you will need to render images through TypoScript (not my favorite way anymore after introducing DataProcessor ;) You can use the below snippet.
10 = IMAGE
10 {
file = fileadmin/sample.jpg
file.width = 3141
layoutKey = default
layout {
[...]
srcset {
element = <img src="###SRC###" srcset="###SOURCECOLLECTION###" ###PARAMS### ###ALTPARAMS### ###SELFCLOSINGTAGSLASH###>
source = |*|###SRC### ###SRCSETCANDIDATE###,|*|###SRC### ###SRCSETCANDIDATE###
}
[...]
}
{
small {
width = 800
srcsetCandidate = 800w
mediaQuery = (min-device-width: 800px)
dataKey = small
}
[...]
}
}
20 < 10
20.layoutKey = srcset
[...]
6. Using TypoScript in renderObj
I know, you want to use dynamic TypoScript with renderObj - it’s the same. Just create a special object and assign it to renderObject - see below.
// Prepare TypoScript Object for Image Rendering
lib.objResponsiveImage {
default = IMAGE
default {
file {
import.current = 1
treatIdAsReference = 1
}
altText.field = alternative
titleText.field = title
params = class="image-embed-item"
layoutKey = srcset
layout {
[...]
srcset {
element = <img src="###SRC###" srcset="###SOURCECOLLECTION###" sizes="100vw" ###PARAMS### ###ALTPARAMS### ###SELFCLOSINGTAGSLASH###>
source = |*|###SRC### ###SRCSETCANDIDATE###,|*|###SRC### ###SRCSETCANDIDATE###
}
sourceCollection {
mobile {
maxW = 314
srcsetCandidate = 314w
dataKey = mobile
}
[...]
}
}
}
[...]
// Call and Render TypoScript object into renderObj
renderObj < lib.objResponsiveImage.default
renderObj {
[...]
sourceCollection {
tablet {
width = 768
srcsetCandidate = 768w
mediaQuery = (max-device-width: 768px)
dataKey = tablet
}
[...]
}
}
<!-- Render at TYPO3 Fluid -->
<f:cObject
typoscriptObjectPath="lib.objResponsiveImage.default"
data="{file.uid}"
/>
7. Define cropVariants in TCEFORM
The TYPO3 provides unlimited possibilities to create Crop variants for the backend editor like Tablet variant, Mobile variant etc. Using TCEFORM you can define as many variants you want, follow this code snippet.
TCEFORM {
sys_file_reference.crop.config.cropVariants {
default {
title = Alle (Standard)
selectedRatio = NaN
allowedAspectRatios {
NaN {
title = Frei
value = 0.0
}
[...]
4:3 {
title = 4:3
value = 1.333333
}
}
}
card {
title = Card
selectedRatio = 16:9
allowedAspectRatios {
16:9 {
title = 16:9
value = 1.777777778
}
}
}
}
}
<!-- Render at TYPO3 Fluid -->
<img
class="lazy"
data-src="{f:uri.image(src: file, treatIdAsReference: 1, maxWidth: 768, cropVariant: 'card')}"
data-srcset="{f:uri.image(src: file, treatIdAsReference: 1, maxWidth: 768, cropVariant: 'card')} 768w,
{f:uri.image(src: file, treatIdAsReference: 1, maxWidth: 1900, cropVariant: 'card')} 1200"
data-sizes="..."
alt="..."
[...]
/>
8. Using EXT.vhs
The `vhs` is one of the most lovable Fluid TYPO3 extensions. Personally, I wish one day all the features of EXT.vhs will be part of the TYPO3 core fluid. It’s awesome because it’s been developed and maintained by Mr. TYPO3 fluid - Claus ;) Anyway, back to the topic - Using <v:media.image /> TYPO3 fluid viewhelper you can set the `srcset` attribute to create TYPO3 responsive images.
<v:media.image
src="path/to/media.jpg"
width="123"
height="123"
[...]
treatIdAsReference="1"
srcset="314, 768, 990, 1200"
srcsetDefault="768"
/>
9. Using EXT.sms_responsive_images
More than 70K+ downloads, EXT.sms_responsive_images provides ViewHelpers and configuration to render valid responsive images based on TYPO3's image cropping tool. The cool thing about this extension is that, you can define TYPO3 responsive dimensions in many ways.
<sms:image image="{image}" srcset="400, 600, 800, 1000" />
<sms:image image="{image}" srcset="1x, 2x" />
<sms:image
image="{image}"
sizes="(min-width: 1200px) 600px, (min-width: 900px) 800px, 100vw"
/>
<sms:image
image="{image}"
breakpoints="{
0: {'cropVariant': 'desktop', 'media': '(min-width: 1000px)', 'srcset': '1000, 1200, 1400, 1600'},
1: {'cropVariant': 'mobile', 'srcset': '400, 600, 800, 1000, 1200, 1400, 1600'}
}"
/>
<sms:image image="{image}" srcset="400, 600" lazyload="true" />
10. Using EXT.fluid_styled_responsive_images
Less popular TYPO3 extension; Enables creation of responsive images for fluid styled content elements.
tt_content.textmedia {
settings {
responsive_image_rendering {
layoutKey = srcset
sourceCollection {
10 {
dataKey = desktop
width = 1260m
srcset = 1260w
}
20 {
dataKey = table
width = 960m
srcset = 960w
}
}
}
}
}
11. EXT.responsive-images
The extension is not available at TER, but yeah seems pretty good. This extension adds responsive images support for fluid templates using the MediaViewHelper. An integrator can specify image configurations that are used in fluid templates. This extension will also respect cropping variants (introduced in TYPO3 v8) and will handle different jpeg qualities for each image.
<r:loadRegister key="IMAGE_VARIANT_KEY" value="default">
<f:media file="{file}" />
</r:loadRegister>
<picture>
<source media="(max-width: 40em)" srcset="320x180-q65.jpg 1x, 640x360-q40.jpg 2x" />
<source media="(min-width: 64.0625em)" srcset="1920x1080-q80.jpg 1x" />
<source media="(min-width: 40.0625em)" srcset="1024x576-q80.jpg 1x, 2048x1152-q40.jpg 2x" />
<img src="1920x1080.jpg" alt="Example alternative" width="1920" height="1080" />
</picture>
12. Using Custom TYPO3 API ImageProcessorCore (PHP)
Last one is with customer PHP TYPO3 core API; If you really want to manipulate something and display responsive images then TYPO3 is always flexible - Let’s go with custom TYPO3 ImageProcessor.
<?php declare(strict_types=1); namespace YourVendor\YourTemplate\DataProcessing; use TYPO3\CMS\Extbase\Object\Exception; use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer; use TYPO3\CMS\Frontend\DataProcessing\ImageProcessor as ImageProcessorCore; /** * Class ImageProcessor * extends the original ImageProcessor with additional information of the maximum image width * for a better responsive image rendering in Image partial. */ class ImageProcessor extends ImageProcessorCore { /** * @var int[] */ protected $maxWidths = [ 'full' => 1600, // maximum image width if image is over or under a text 'beside' => 800 // maximum image width if image is placed beside a text ]; /** * Max width for fullwidthgallery. Related to the number of images that are included in backend, the maximum width * is calculated. For whatever reason if you only add 3 images, they are very small, but if you add 4 images (2x2) a * a single image can be very large, etc... * * @var array */ protected $maxWidthsFullWidthGallery = [ 1 => 450, // number of images => max width 2 => 450, 3 => 450, 4 => 1400, // Change from 1 to 2 rows 5 => 450, 6 => 900, 7 => 450, 8 => 650, 9 => 450, 10 => 520, 11 => 450, 12 => 450, 13 => 450, // Change from 2 to 3 rows 14 => 450 ]; /** * @param ContentObjectRenderer $cObj The data of the content element or page * @param array $contentObjectConfiguration The configuration of Content Object * @param array $processorConfiguration The configuration of this processor * @param array $processedData Key/value store of processed data (e.g. to be passed to a Fluid View) * @return array the processed data as key/value store * @throws Exception */ public function process( ContentObjectRenderer $cObj, array $contentObjectConfiguration, array $processorConfiguration, array $processedData ) { $processedData = parent::process($cObj, $contentObjectConfiguration, $processorConfiguration, $processedData); $processedData = $this->extendDimensions($processedData); return $processedData; } /** * @param array $processedData * @return array */ protected function extendDimensions(array $processedData): array { foreach ((array)$processedData['gallery']['rows'] as $rowKey => $row) { foreach ((array)$row['columns'] as $columnKey => $column) { if (!empty($column['dimensions'])) { if ((int)$processedData['data']['layout'] !== 30) { $maxWidth = $this->calculateMaxWidthForTextMedia($processedData, $row); } else { $maxWidth = $this->calculateMaxWidthForFullWidthGallery($processedData['gallery']['rows']); } $processedData['gallery']['rows'][$rowKey]['columns'][$columnKey]['dimensions']['maxWidth'] = $maxWidth; } } } return $processedData; } /** * @param array $processedData * @param array $row * @return int */ protected function calculateMaxWidthForTextMedia(array $processedData, array $row): int { $maxWidth = $this->maxWidths['full']; if ($processedData['data']['imageorient'] !== 0 && $processedData['data']['imageorient'] !== 8) { $maxWidth = $this->maxWidths['beside']; } if (count($row) > 0) { $maxWidth = (int)ceil($maxWidth / count($row)); } return $maxWidth; } /** * @param array $rows * @return int */ protected function calculateMaxWidthForFullWidthGallery(array $rows): int { $numberOfImages = count($rows); $maxWidth = $this->maxWidthsFullWidthGallery[0]; if (array_key_exists($numberOfImages, $this->maxWidthsFullWidthGallery)) { $maxWidth = $this->maxWidthsFullWidthGallery[$numberOfImages]; } return $maxWidth; } }
<!-- TYPO3 Fluid --> <html xmlns:f="https://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" data-namespace-typo3-fluid="true"> <picture> <f:comment> {dimensions.maxWidth} is calculated with a DataProcessor and should show the maximum possible image width. </f:comment> <f:if condition="{dimensions.maxWidth} > 1601"> <source srcset="{f:uri.image(image:file, maxWidth: 2561, fileExtension: 'webp')}" media="(min-width: 1601px)" type="image/webp"> <source srcset="{f:uri.image(image:file, maxWidth: 2560, fileExtension: 'jpg')}" media="(min-width: 1601px)" type="image/jpeg"> </f:if> <f:if condition="{dimensions.maxWidth} > 1201"> <source srcset="{f:uri.image(image:file, maxWidth: 1601, fileExtension: 'webp')}" media="(min-width: 1201px)" type="image/webp"> <source srcset="{f:uri.image(image:file, maxWidth: 1600, fileExtension: 'jpg')}" media="(min-width: 1201px)" type="image/jpeg"> </f:if> <f:if condition="{dimensions.maxWidth} > 769"> <source srcset="{f:uri.image(image:file, maxWidth: 1201, fileExtension: 'webp')}" media="(min-width: 769px)" type="image/webp"> <source srcset="{f:uri.image(image:file, maxWidth: 1200, fileExtension: 'jpg')}" media="(min-width: 769px)" type="image/jpeg"> </f:if> <f:if condition="{dimensions.maxWidth} > 481"> <source srcset="{f:uri.image(image:file, maxWidth: 769, fileExtension: 'webp')}" media="(min-width: 481px)" type="image/webp"> <source srcset="{f:uri.image(image:file, maxWidth: 768, fileExtension: 'jpg')}" media="(min-width: 481px)" type="image/jpeg"> </f:if> <source srcset="{f:uri.image(image:file, maxWidth: 481, fileExtension: 'webp')}" type="image/webp"> <source srcset="{f:uri.image(image:file, maxWidth: 480, fileExtension: 'jpg')}" type="image/jpeg"> <img class="image-embed-item" title="{file.title}" alt="{file.description -> f:format.nl2br()}" src="{f:uri.image(image:file, maxWidth: 1600)}" width="{dimensions.width}" height="{dimensions.height}" loading="{settings.media.lazyLoading}" /> </picture> </html>
// Assign with TypoScript Object tt_content.textmedia.dataProcessing { // Overwrite original ImageProcessor 20 = YourVendor\YourTemplate\DataProcessing\ImageProcessor }
Bonus: TYPO3 + WebP
From TYPO3 version 10.3 it is now possible with the ViewHelper <f: image> , <f: media> and <f: uri.image> for the argument file extension option webp specify:
<picture>
<source srcset="{f:uri.image(image: file, treatIdAsReference: true, fileExtension: 'webp')}" type="image/webp"/>
<source srcset="{f:uri.image(image: file, treatIdAsReference: true, fileExtension: 'jpg')}" type="image/jpeg"/>
<f:image alt="{file.alternative}" image="{file}" treatIdAsReference="true"/>
</picture>
It should be checked beforehand whether the ImageMagick version used supports the WebP conversion.
Tips:
Did you know to allow/disallow particular file extensions? e.g., Allow webp file extension. You can configure it in this way ;)
$GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'] = 'gif,jpg,jpeg,tif,tiff,bmp,pcx,tga,png,pdf,ai,svg,webp';
Instantly Create Responsive Images with TYPO3 AI
Creating responsive images for your TYPO3 website is essential for maintaining high standards. With the T3AI TYPO3 AI Extension, this process becomes faster and simpler. Powered by advanced AI models, T3AI allows you to generate high-quality, responsive images in seconds—no complex steps needed. Just click, and let the AI handle the rest! This easy-to-use tool ensures your images are perfectly optimized for all devices, improving site performance and user experience.
Post a Comment
- Responsive design is an absolute must, and this Blog offers a dozen creative solutions to tackle TYPO3 image responsiveness.
- I've struggled with responsive images in TYPO3 for a while, but this article simplified the entire process.The practical examples and step-by-step instructions are a huge help.
Sanjay Chauhan
CTO - T3Planet & NITSANSanjay Chauhan, Mitbegründer von NITSAN (Preisgekrönte TYPO3 Agentur) und Pionier von T3Planet, dem ersten TYPO3 Shop weltweit.
Ein wahrer TYPO3-Fanatiker seit 2010.
Mit meinem umfangreichen technischen Wissen und…
More From Author
Sanjay Chauhan
CTO at T3Planet & NITSANSanjay Chauhan, Co-Founder of NITSAN (Award winning TYPO3 agency) and Pioneer of T3Planet (first-ever TYPO3 Shop).
A true TYPO3 fanatic since 2010. I bring strong TYPO3 experience in building customer-business…
More From Author