12 Ways To Create TYPO3 Responsive Images!

Make your TYPO3 site modern- In this article, you will find 10+ possible ways to create responsive images using TYPO3 core and TYPO3 extensions.

12 Ways To Create TYPO3 Responsive Images!

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';

Closure!

That’s it! I hope you learn and enjoy reading this TYPO3 article.

What’s your favourite way to create TYPO3 responsive images? Or Do you have any other way to integrate it? I would love to know your thoughts in the comment box.

Have a Happy TYPO3 Responsive Images!

Your One Stop Solutions for Custom TYPO3 Development

  • A Decade of TYPO3 Industry Experience
  • 250+ Successful TYPO3 Projects
  • 87% Repeat TYPO3 Customers
Get Your Free Quote

Post a Comment

×
  • user
    Niklas 2023-09-05 at 3:05 pm
    Responsive design is an absolute must, and this Blog offers a dozen creative solutions to tackle TYPO3 image responsiveness.
  • user
    Michael Wulf 2023-09-05 at 3:03 pm
    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.
  • user
    Dave Chamberlin 2023-07-29 at 12:58 am
    Hi t3planet.com administrator, Your posts are always a great source of information.
  • user
    Jonas Sanger 2023-07-14 at 3:13 pm
    This article on TYPO3 responsive images was exactly what I needed to enhance my web development skills.
  • user
    Alexander 2023-07-14 at 3:03 pm
    I found your article on TYPO3 responsive images incredibly helpful!