Responsive Images with TYPO3 8.7

Responsive webdesign is a de-facto standard in the modern web now. We usually design websites with both small and big screens in mind. However, we often stop when it comes to embedded images. In most cases, there will be one image file that is (kind of) optimized for desktop usage, which will then be used across all screen sizes. We can do better with responsive images.

On a typical website, responsive images are able to

  • reduce bandwidth on mobile devices due to smaller image sizes
  • reduce loading times on mobile devices, also due to smaller image sizes
  • produce sharper images for devices with high dpi screens (such as Apple’s „retina“ screens)

If properly configured, responsive images are clearly a win-win feature: Users like fast, mobile-friendly websites and website owners like satisfied users.

How do responsive images work?

Ask two web developers what responsive images are and you get three opinions. The good news is that, while the response to this question was quite complicated a few years ago, nowadays it should be straightforward.

The HTML5 standard specifies three new features to implement responsive images in modern web browsers. Actually, the browser support is pretty good, which is why responsive images should be a nobrainer. And for older browsers, there is a polyfill for responsive images called picturefill.

The srcset attribute

With the srcset attribute you can provide additional image files to the browser. These files have to show the identical image and should only vary in their dimensions. This is important because the browser is free to choose which image will be used in the current environment. While current browsers base their decision mainly on the current viewport size and the pixel density of the screen, this may change in the future. Thus, you cannot use srcset to define which exact file will be used on a specific device!

The following example defines an image with three additional image files, one 400 pixels, one 800 pixels and one 1200 pixels wide.

    image@400.jpg 400w,
    image@800.jpg 800w,
    image@1200.jpg 1200w
  alt="alternative text"

The sizes attribute

The sizes attribute gives the browser hints about what image should be used in the current environment. Without a sizes attribute, the browser doesn’t know in which size the image will be displayed on the page and can’t decide intelligently which image file should be downloaded.

    image@400.jpg 400w,
    image@800.jpg 800w,
    image@1200.jpg 1200w
  sizes="(min-width: 800px) 800px, 100vw"
  alt="alternative text"

The sizes query in this example translates to the following:

If the viewport width is larger than 800 pixels, this image tag will be 800 pixels wide. If the viewport is less wide, the image tag will fill the whole viewport width.

Thus, the 1200w file will only be used on high dpi screens.

The picture tag

Last but not least, there is the <picture> tag. Apart from some other useful features, picture allows something called art direction. This means that you can provide different images based on CSS media queries – usually the viewport width. This is exactly the feature srcset can’t provide: To force the browser to load a specific image at a defined breakpoint.

This allows you to use a square image on mobile and a wide image on desktop screens. The following example would display desktop.jpg on screens above 600 pixels and mobile.jpg on smaller screens:

  <source srcset="desktop.jpg" media="(min-width: 600px)" />
  <source srcset="mobile.jpg" />
  <img src="image.jpg" alt="alternative text" />

As you might have guessed, both srcset and sizes can be used for each <source> tag, which makes the <picture> tag both powerful and complex.

What changed with TYPO3 8.7?

With TYPO3 8.7, the image cropping tool in the backend was extended to allow multiple crop variants for each image:

This feature is the missing element to generate real responsive images with TYPO3. For example, it would allow you to define two cropping configurations for one image – one for mobile devices and one for desktop:

These crop variants can be defined either in TCA or in Page TSconfig, as described in the feature documentations linked above.

How to render responsive images?

While these changes are all nice and fine, what is missing in TYPO3 8.7 is a way to render those images in the frontend in a convenient way. This is why we at sitegeist developed an extension called sms_responsive_images. It contains the necessary Fluid ViewHelpers to render both <img> tags with srcset/sizes and whole <picture> tags. It also tweaks the rendering of fluid_styled_content to generate responsive images by default, so your content images get upgraded to responsive images automatically.

For custom content elements, such as Mask elements or Extbase plugins with their own Fluid templates, you can use the included ViewHelpers to tweak the image rendering:

img tag with srcset/sizes

The following snippet would generate the <img> tag with srcset and sizes I used in the example above.

<sms:image image="{image}" srcset="400, 800, 1200" sizes="(min-width: 800px) 800px, 100vw" />

Another and probably the better way to achieve this would be to simply set the width attribute for the tag:

<sms:image image="{image}" srcset="400, 800, 1200" width="800" />

This serves two purposes: It sets a reasonable default width for the fallback image (otherwise it would be the original image size) and it generates a sizes query based on the specified width.

picture tag

To generate a <picture> tag, you have to combine the new crop variants with some additional configuration:

<sms:image image="{image}" width="800" breakpoints="{
  0: {'cropVariant': 'desktop', 'media': '(min-width: 600px)',
    'srcset': '600, 800, 1000, 1200, 1400, 1600'},
  1: {'cropVariant': 'mobile',
    'srcset': '400, 600, 800, 1000, 1200', 'sizes': '100vw'}
}" picturefill="false" />

(I added the picturefill attribute to get a simpler and cleaner result, usually you wouldn’t do that.)

This would result in the following <picture> tag:

      desktop@600.jpg 600w,
      desktop@800.jpg 800w,
      desktop@1000.jpg 1000w,
      desktop@1200.jpg 1200w,
      desktop@1400.jpg 1400w,
      desktop@1600.jpg 1600w
    media="(min-width: 600px)"
    sizes="(min-width: 800px) 800px, 100vw"
      mobile@400.jpg 400w,
      mobile@600.jpg 600w, 
      mobile@800.jpg 800w, 
      mobile@1000.jpg 1000w,
      mobile@1200.jpg 1200w
  <img src="image.jpg" width="800" alt="" />

To recap, this is how the image would behave:

  • For mobile screens under 600 pixels, it would choose one of the mobile@ images based on the viewport width and pixel density of the screen.
  • For desktop screens above 600 pixels, it would choose one of the desktop@ images.
    • If the viewport width is smaller than 800 pixels, it will choose based on the whole viewport width.
    • If it’s larger, 800 pixels will be the maximum width.

A screen at 1000px viewport width and a pixel density of 2 would likely display desktop@1600.jpg. A screen at 400px viewport width and a pixel density of 1.5 would likely display mobile@600.jpg.

How can I get this?

You can download the extension either via composer:

composer require sitegeist/sms-responsive-images

or from TYPO3 TER:

TYPO3 TER: sms_responsive_images

To setup the extension, you should take a look at the documentation:

Extension Documentation

You can also take a look into the code at GitHub:

GitHub: sitegeist/sms-responsive-images

I really hope that this extension will help to spread the usage of responsive images in the TYPO3 community. With images being the largest files on most websites (apart from audio/video of course) and always increasing mobile usage of the world wide web, it should be a goal for all of us to serve the user the fastest loading and smallest possible website while still having great image quality. And we can achieve that with responsive images.

7 Gedanken zu „Responsive Images with TYPO3 8.7“

  1. Hallo Sitegeist-Team,

    großes Lob an Euch für die super Extension. Wir sind gerade dabei ein Projekt damit umzusetzen und hatten ursprünglich den Ansatz neben responsiven Bildern auch Lazyload zu verwenden. Allerdings zieht sich Lazyload seine Daten ursprünglich aus dem data-src und data-srcset Attribut.

    Seht ihr eine Möglichkeit, auch hierfür Eure Extension zu verwenden oder zu erweitern, sodass sie trotzdem pflegbar bleibt?



    1. Hallo Christoph,

      zuerst mal danke für das Lob! Freut uns natürlich zu hören, dass die Extension gut ankommt.

      Zu deinem Anliegen: Aktuell geplant ist es nicht, die Extension um ein Lazyloading zu erweitern. Ich habe dafür aber mal ein Ticket im GitHub-Projekt der Extension erstellt: Add lazyloading attribute #7

      Als kurzfristige Lösung könntet ihr die beiden ViewHelper in einer eigenen Extension erweitern und den generierten Tag ($this->tag) vor der Ausgabe modifizieren. Natürlich freuen wir uns auch über einen Pull-Request auf GitHub, der die Extension entsprechend erweitert!

      Viele Grüße

  2. Hi, thanks as well for this nice and needed extension 🙂

    Question about further optimization requirements:
    RWD images are set in this case by the viewport of the browser. Concering the size and dimensions of an image, this works fine if you have 1 col content. But building websites includes also 2 or 3 cols and here the element loads on destop view the max. size of an image. Due to the smaller cols, actually we only need maybe 600px width images for 2 col and even smaller once for 3 col. How you guys handle this problem? Actually in the backend there should be an option where editors can choose, which max size they need for this image if it embedded in cols.

    best regards

    1. Hi Florian,

      the key to solve this problem is to adjust the sizes attribute of the image tags.

      The first thing to do is to define a maximum width for tt_content images that is as big as the maximum image width in the primary column. This can be done by setting the TypoScript constant styles.content.textmedia.maxW. This in combination with the default sizes query of the extension limits the image sizes in the frontend.

      If you want to do more, you can take a look at the default TypoScript and the Fluid templates of fluid_styled_content. There, you can override certain parts of the rendering TypoScript per column, e. g.:

      contentLeft = CONTENT
      contentLeft {
        table = tt_content
        select {
          orderBy = sorting
          where = colPos=1
          languageField = sys_language_uid
        renderObj < tt_content
        renderObj {
          image.settings.tx_smsresponsiveimages.sizes = (min-width: 300px) 300px, 50vw

      This setting will then be used in the Fluid templates to override the default sizes query for the left column.

      I hope this helps.

Kommentare sind geschlossen.