PunktDe Kontakt LogoKontakt
Schließen
Just type and press enter to search
Cancel

Responsive Images in TYPO3 v10

Responsive Images in TYPO3 v10

Standard-Image-Rendering

Images in TYPO3 v10 are usually rendered using a Fluid-ViewHelper. Here the media-ViewHelper is used, which renders the corresponding HTML markup depending on the resource (image or video). The fluid markup relevant for us is located in the file 

typo3/sysext/fluid_styled_content/Resources/Private/Partials/Media/Rendering/Image.html:

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

The whole markup is very lightweight - which surprised me positively.The documentation of the media-ViewHelper https://docs.typo3.org/other/typo3/view-helper-reference/master/en-us/typo3/fluid/latest/Media.html shows besides the arguments presented here some more, like the new argument loading. The argument loading is available for the media-ViewHelper as of v10.3 and is used by default with the value lazyH.  The constant introduced by fluid_styled_content for this purpose, styles.content.image.lazyLoading, can be used to customize the loading argument (lazy, eager or auto). There is an explanation of the loading attribute here: https://web.dev/native-lazy-loading/#the-loading-attribute

And this is what the HTML output looks like when using the code shown above:

<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="Demo Bild Title Text" alt="Demo Bild Alt Text" src="/fileadmin/_processed_/6/e/csm_image_01_a55d08e819.jpg" loading="lazy" width="600" height="337">
                            </figure>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

As you can see, the already mentioned loading attribute was rendered with the value lazy. The HTML construct around the img tag is derived from other fluid templates, most of which are located here: typo3/sysext/fluid_styled_content/Resources/Private/Partials/Media/. Let's take a closer look at the media-ViewHelper.

adapt media-ViewHelper

The media-ViewHelper lacks arguments like srcset or sizes. But the attribute srcset is necessary so that we can overwrite the src-attribute of an image with a set of image sources. To integrate both arguments, we need an own fluid partial that overwrites the original (...Partial/Media/Rendering/Image.html). For this I have created my own small extension (responsive_images_demo) at https://www.sitepackagebuilder.com/ - based on TYPO3 v10 and Fluid Styled Content.

With the following constants you can specify where your own parts or templates are located:

styles {
    templates {
        layoutRootPath = EXT:responsive_images_demo/Resources/Private/Layouts/ContentElements/
        partialRootPath = EXT:responsive_images_demo/Resources/Private/Partials/ContentElements/
        templateRootPath = EXT:responsive_images_demo/Resources/Private/Templates/ContentElements/
    }
}

My own image partial is located at typo3conf/ext/responsive_images_demo/Resources/Private/Partials/ContentElements/Media/Rendering/Image.html and automatically overwrites the original (typo3/.../Partial/Media/Rendering/Image.html).

integrate srcset / sizes

The media-ViewHelper is supplemented with the attributes srcset and sizes using the ViewHelpers uri.image and the Argument 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'}"
/>

The shown srcset and sizes are exemplary here. For which instrument characteristics you want to provide the corresponding resolutions is of course up to you.

And this is how the HTML output looks like in the frontend:

<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="Demo Bild Title Text"
    alt="Demo Bild Alt Text"
    src="/fileadmin/_processed_/6/e/csm_image_01_a55d08e819.jpg"
    loading="lazy"
    width="600"
    height="337"
>

The attributes width and height can be adjusted using the following constants:

  • styles.content.textmedia.maxW
  • styles.content.textmedia.maxWInText - Like maxW but this is the maximum width when text is wrapped around a block of media elements. Default value is 50% of the normal maximum media element width → maxW)

The default value in TYPO3 v10.4 is 600 for maxW and 300 for maxWInText.

Alternative fluid variant

img tag

An alternative way to render responsive images instead of using f:media or f:image is to use a common img tag in combination with the f:uri.image ViewHelper:

Die Attribute width und height können über folgende Konstanten angepasst werden:

  • styles.content.textmedia.maxW
  • styles.content.textmedia.maxWInText - Wie maxW aber hierbei handelt es sich um die maximale Breite, wenn Text um einen Block von Medien-Elementen umgebrochen wird. Standardwert ist 50 % der normalen maximalen Medien-Elementbreite → maxW)

Der Standardwert in TYPO3 v10.4 ist für maxW → 600 und für maxWInText → 300.

Alternative Fluid Variante

img Tag

Eine alternative Variante um Responsive Images anstelle unter zu Hilfenahme von f:media oder f:image zu rendern, kann die Verwendung eines ganz gewöhnlichen img Tags in Kombination mit dem f:uri.image ViewHelper sein:

<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}"
/>

In the example, the attributes src, srcset and sizes are given the data prefix, which is often needed for lazy loading scripts such as https://github.com/verlok/lazyload 

picture tag

The picture tag can be equipped with the f:uri.image ViewHelper as a further variant, like the img tag example shown:

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

TypoScript variant

In the past, Responsive Images were very often rendered by TypoScript, but later on, due to the increasing popularity of Fluid, this was more and more superseded. Nevertheless, TypoScript rendering of Responsive Images still has its reasons, especially if the site is (still) largely rendered in TypoScript. TypoScript is a powerful tool and offers great flexibility in rendering. Sometimes TypoScript elements can be rendered more easily with a few lines of TypoScript than with nested fluid constructs. Just a look at the documentation of the TypoScript IMAGE object shows the potential: https://docs.typo3.org/m/typo3/reference-typoscript/master/en-us/ContentObjects/Image/Index.html 

The next TypoScript examples show only the areas that are relevant for Responsive Images. The IMAGE documentation mentioned above contains complete examples and their HTML output.

The example shows a typical IMAGE object that has been extended by various properties, so that it gets e.g. the srcset attribute (###SRCSETCANDIDATE###):

10 = IMAGE
10 {
  file = fileadmin/example.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
 
[...]

For example, the IMAGE object can be defined as a reusable TypoScript object lib.responsiveImage:

lib.responsiveImage {
    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
            }
            [...]
        }
    }
}
 
[...]
 
renderObj < lib.responsiveImage.default
renderObj {
    [...]
  
    sourceCollection {
        tablet {
            width = 768
             
            srcsetCandidate = 768w
            mediaQuery = (max-device-width: 768px)
            dataKey = tablet
        }
 
        [...]
    }
}

or in a fluid template:

<f:cObject
    typoscriptObjectPath="lib.responsiveImage.default"
    data="{file.uid}"
/>

Cropping

Since some TYPO3 versions (v7.6) the crop feature exists, which gives editors a tool to define a section of an image. The next two code sections should show a possible way to adjust the crop variants available in the backend for image manipulation and how the sections can be accessed.

TCEFORM

The crop variant default, which TYPO3 already comes with, as well as additional variants can be customized via TCEFORM:

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
                }
            }
        }
    }
}

The property allowedAspectRatios can be used to specify different aspect ratios. This gives the editor different pre-defined aspect ratios for an image, for example to select the appropriate aspect ratio for certain layout specifications more quickly. In the above example, the new variant card was added to the default variant, which is overwritten here. If only one new variant is defined, such as the card variant in the example, the user is not provided with a default variant in the back end.

Fluid

In the fluid template, the corresponding variant is accessed via the cropVariant argument of the f:uri.image ViewHelper. In this example on card:

<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="..."
    [...]
/>

As a supplement I would like to mention the way via TCA
https://docs.typo3.org/m/typo3/reference-tca/master/en-us/ColumnsConfig/Type/ImageManipulation.html

It is worthwhile to have a look at the TCA documentation, because among other things the use of the coverArea is shown, e.g. to show image areas for the editor, which can contain a text area in the frontend that later covers the image, or the focusArea property that stores coordinates (focal point), which can be used e.g. for JavaScript plugins like https://github.com/jonom/jquery-focuspoint.

Extensions

If you want to save yourself some typing work when integrating the Responsive Images into Fluid or TypoScript, or if you need more functionality than the Fluid-ViewHelpers such as f:media or f:image offer, you can always look around for TYPO3 extensions: In the TYPO3 community, the following two TYPO3 extensions are often used for rendering Responsive Images:

vhs media ViewHelper

The vhs TYPO3 extension offers a variety of useful ViewHelper, including the v:media.image ViewHelper, which has similarities to the well-known ViewHelper f:media or f:image. A first look at the vhs-ViewHelper already shows the simplicity with which e.g. the different srcset specifications can be defined:

<v:media.image
    src="path/to/media.jpg"
    width="123"
    height="123"
    [...]
    treatIdAsReference="1"
    srcset="314, 768, 990, 1200"
    srcsetDefault="768"
/>

The v:media.image ViewHelper reference lists some more interesting arguments: https://fluidtypo3.org/viewhelpers/vhs/master/Media/ImageViewHelper.html

sms_responsive_images

Besides vhs the TYPO3 extension sms_responsive_images is another recommendation. Again, the fluid configuration is relatively simple and has some features at hand:

<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" />

The extension renders an <img> or <picture> tag, depending on which arguments are used. For example, a picture tag is rendered when using the breakpoints argument. 

In the extension documentation you will find examples of how to render a picture tag in addition to the ones shown here: https://extensions.typo3.org/extension/sms_responsive_images

Bonus

fileExtension / WebP

Starting with TYPO3 v10.3 it is now also possible to specify the option webp for the argument fileExtension in the ViewHelpers <f:image>, <f:media> and <f:uri.image>:

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

You should first check whether the ImageMagick version you are using supports WebP conversion. 

Find links to further information on using WebP in conjunction with TYPO3 below:

Autor: Martin Alker

Comments

Bisher wurden keine Kommentare eingereicht.

Other Posts

29. Mai 2020

Responsive Images in TYPO3 v10

In this article I would like to talk about the integration of Responsive Images in TYPO3 v10. Most of … more

29. August 2019

Your Neos Project on a proServer – in Five Minutes with Ansible

The proServer by punkt.de comes with all services and tools that are necessary for sophisticated Neos … more