Responsive images - srcset and picture tags

Hello everyone,

i struggled in generally with srcset and picture tags. I never used before, but now with web vitals and modern image formats, it is a must have.

So I created a setup with an image partial to generate my img markups like this:

title = "Image Partial"
description = "This image partial is made to be reusable on all pages. See comments in markup."
==
<picture {{ additional_attributes|default('') }}>
    {# Convert sizes string to array #}
    {% set sizes_array = sizes_string|split(',') %}

    {# WebP image source #}
    <source type="image/webp" srcset="
        {{ image_url | resize(sizes_array[0], null, { mode: 'crop', quality: 80, extension: 'webp' }) }} {{ sizes_array[0] }}w,
        {{ image_url | resize(sizes_array[1], null, { mode: 'crop', quality: 80, extension: 'webp' }) }} {{ sizes_array[1] }}w,
        {{ image_url | resize(sizes_array[2], null, { mode: 'crop', quality: 80, extension: 'webp' }) }} {{ sizes_array[2] }}w" sizes="(min-width: {{ sizes_array[0] }}px) {{ sizes_array[0] }}px, (min-width: {{ sizes_array[1] }}px) {{ sizes_array[1] }}px, {{ sizes_array[2] }}px">

    {# Fallback image source for browsers that don't support WebP format #}
    {% set resized_image_url = image_url | resize(resize_width, resize_height, { mode: 'crop', quality, extension: 'webp' }) %}
    <img src="{{ resized_image_url }}" width="{{ default_width }}" height="{{ default_height }}" alt="{{ alt_text }}" loading="{{ loading }}" class="{{ class_names }}" {{ additional_attributes|default('') }}>
</picture>

This I store in “partials/utility/_image-partial.htm”. On my page I use it like this:

{% set image_url = 'assets/images/test/background.jpg' %}
    {% set sizes_string = '455,768,890' %}
         {% partial 'utility/_image-partial'
             image_url=image_url|theme
             resize_width='2560'
             resize_height='1120'
             default_width='2560'
             default_height='1120'
             alt_text='Demo image'
             loading='eager'
             class_names='el-image'
             sizes=sizes_string
             additional_attributes='data-uk-cover'
%}

This way I have an easy setup and can generate my picture tags on the fly. May someone have some ideas to improve this setup or even it can be a core feature to generate this markup. As far as I know Statamic CMS has some feature.

Have a nice day!

4 Likes

Hello!
I like this and it’s more refined than what I’m usually using in my projects.
I often have this problem with the quality of the images being too low (blurry or pixelated) when using the resize filter. From what I understood, it’s using the “stock” PHP image manipulation features, which are known to mess up the quality, even if set on 100.
Did you have any problems with this?

Hey!

Thanks for joining in.

So far I don’t have any problems with the quality of the images. It works well.

Have a nice day!

1 Like

Just for note, here is how I do it:

<picture>
<source type="image/webp" media="(min-width: 1px) and (max-width: 600px)" srcset="{{ store.featured_image.getThumb(600, 374, {'mode': 'auto', 'quality': 85, 'extension': 'webp'}) }}">
<source type="image/jpeg" media="(min-width: 1px) and (max-width: 600px)" srcset="{{ store.featured_image.getThumb(600, 374, {'mode': 'auto', 'quality': 85, 'extension': 'jpeg'}) }}">
<source type="image/webp" media="(min-width: 601px) and (max-width: 800px)" srcset="{{ store.featured_image.getThumb(800, 498, {'mode': 'auto', 'quality': 85, 'extension': 'webp'}) }}">
<source type="image/jpeg" media="(min-width: 601px) and (max-width: 800px)" srcset="{{ store.featured_image.getThumb(800, 498, {'mode': 'auto', 'quality': 85, 'extension': 'jpeg'}) }}">
<source type="image/webp" media="(min-width: 801px) and (max-width: 8800px)" srcset="{{ store.featured_image.getThumb(636, 396, {'mode': 'auto', 'quality': 85, 'extension': 'webp'}) }}">
<source type="image/jpeg" media="(min-width: 801px) and (max-width: 8800px)" srcset="{{ store.featured_image.getThumb(636, 396, {'mode': 'auto', 'quality': 85, 'extension': 'jpeg'}) }}">
<img 
	width="800" height="498"
	loading="lazy" 
	class="img-fluid rounded-top-2 rounded-top-md-4 rounded-md-4" 
	src="{{store.featured_image.getThumb(636, 396, {'mode': 'crop', 'quality': 85, 'extension': 'jpg'}) }}"
	alt="{{store.featured_image.title}}" 
	title="{{store.featured_image.description}}"
>
</picture>
1 Like