<p>You can use the method <a href="https://docs.craftcms.com/api/v3/craft-elements-asset.html#method-getsrcset" rel="noreferrer"><code>Asset::getSrcset</code></a> to generate a valid <code>srcset</code> attribute as well as the asset transforms included in it. But you will need to restructure your HTML a bit. The current approach works, but is very verbose and not optimal for different screen resolutions and image placements.</p>
<p>Instead of using multiple source, just use one source without a <code>media</code> attribute that includes all variants in its <code>srcset</code>. Then add a <code>sizes</code> attribute that will tell the browser how large the image will be displayed depending on the viewport width. If the image always spans the full page, you can just set your <code>sizes</code> attribute to <code>100vw</code> (100 viewport width units). If your image is sized differently depending on the viewport, you will need to adjust the sizes attribute to match those sizes. <a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images" rel="noreferrer">Here's a great article on MDN on responsive images, including how to use the <code>sizes</code> attribute</a>.</p>
<p>Now the final code can look like this:</p>
<pre class="lang-twig prettyprint-override"><code>&lt;picture&gt;
    &lt;source {{ attr({
        type: 'image/jpeg',
        srcset: image.getSrcset(
            [320, 360, 412, 600, 768, 1024, 1280, 1440, 1600, 1920, 2560],
            { format: 'jpg', }
        ),
        sizes: '100vw',
    }) }}&gt;
    &lt;img width=&quot;{{ image.width }}&quot; height=&quot;{{ image.height }}&quot; alt=&quot;{{ image.alt }}&quot;&gt;
&lt;/picture&gt;
</code></pre>
<p>The great thing about this approach is that browsers will take care of adjusting for pixel density for you. If you open the page with this image on a smartphone with a 360px wide display (CSS pixels) and a 2x display density (so a 720px screen), the browser will automatically select the 768px image, since it's the smallest available size that's large enough for the screen's resolution and density.</p>
<p>Note that as per the spec browsers <em>may</em> select images based on other factors, such as using a smaller images if network conditions are poor, or using a cached image even if it's smaller than the currently required resolution. But in practice this rarely matters.</p>
<p>By the way, with the code above, you can very easily add a second <code>&lt;source&gt;</code> with the same <code>srcset</code> and <code>sizes</code> attributes but using type <code>image/webp</code> and <code>format: 'webp'</code> in the transform to generate WebP variants of the images for browsers that support it. This will have a large impact on web performance.</p>

CC BY-SA 4.0
2022-02-22T18:38:13.307Z
Perfect thank you a lot for helping me. I take the opportunity to ask you how precise you are in determining the various image sizes and how many you usually generate (for how many resolutions)?
Samuel
CC BY-SA 4.0
2022-02-22T19:01:59.120Z
I have noticed that by using imagerx there are significant performance improvements (a lot less database queries). Do you use such a plugin for responsive images?
Samuel
CC BY-SA 4.0
2022-02-23T08:59:49.317Z
@Samuel Most of our projects have containers with fixed widths (per viewport) and a multi-column layout (using Bootstrap, for example), so we have ~6 different fixed sizes in pixels – though it depends on the image positioning. For an image that stretches the whole viewport, there's only a single size. Then we generate the srcset with those sizes as well as some others for different pixel densities. You can't get every size in every possible resolution, that would be hundreds of images, so we usually just 'fill in the gaps' between sizes so that most devices will find a suitable image.
MoritzLost
CC BY-SA 4.0
2022-02-23T09:02:32.030Z
@Samuel We don't use a plugin, the built-in image resizer works just fine for us. The resizing is a one-time operation for each placed image, after all, and the HTML output can be cached, avoiding excessive queries for most requests. BTW we have a reusable twig template to take care of this stuff, every other template just includes that template and passes it an image, the `sizes` attribute and the list of sizes for the `srcset`. I've written a bit about that here: https://craftcms.stackexchange.com/a/38383/11705
MoritzLost
CC BY-SA 4.0
2022-02-23T14:14:09.710Z
Great! thank you so much for your valuable answers
Samuel
CC BY-SA 4.0
2022-02-22T16:16:42.503Z
2022-02-22T16:16:42.503Z
MoritzLost
<p>I'm new to craft cms and I'm trying to generate srcset sizes for an image with the following code.</p>
<pre><code>{% set thumb320 = { width: 320, format: 'jpg' } %}
{% set thumb320_2x = { width: 640, format: 'jpg' } %}
{% set thumb360 = { width: 320, format: 'jpg' } %}
{% set thumb360_2x = { width: 640, format: 'jpg' } %}
{% set thumb412 = { width: 414, format: 'jpg' } %}
{% set thumb412_2x = { width: 828, format: 'jpg' } %}
{% set thumb600 = { width: 600, format: 'jpg' } %}
{% set thumb600_2x = { width: 1200, format: 'jpg' } %}
{% set thumb768 = { width: 603, format: 'jpg' } %}
{% set thumb768_2x = { width: 1206, format: 'jpg' } %}
{% set thumb1024 = { width: 803, format: 'jpg' } %}
{% set thumb1024_2x = { width: 1606, format: 'jpg' } %}
{% set thumb1280 = { width: 1003, format: 'jpg' } %}
{% set thumb1280_2x = { width: 2006, format: 'jpg' } %}
{% set thumb1440 = { width: 1120, format: 'jpg' } %}
{% set thumb1440_2x = { width: 2240, format: 'jpg' } %}
{% set thumb1600 = { width: 1224, format: 'jpg' } %}
{% set thumb1600_2x = { width: 2448, format: 'jpg' } %}
{% set thumb1920 = { width: 1244, format: 'jpg' } %}
{% set thumb1920_2x = { width: 2488, format: 'jpg' } %}
{% set thumb2560 = { width: 1368, format: 'jpg' } %}

&lt;picture&gt;
    &lt;source media='(min-width: 2560px)' srcset=&quot;{{ image.getUrl(thumb2560) }} 1x&quot;&gt;
    &lt;source media='(min-width: 1920px)' srcset=&quot;{{ image.getUrl(thumb1920) }} 1x, {{ image.getUrl(thumb1920_2x) }} 1.5x&quot;&gt;
    &lt;source media='(min-width: 1600px)' srcset=&quot;{{ image.getUrl(thumb1600) }} 1x, {{ image.getUrl(thumb1600_2x) }} 1.5x&quot;&gt;
    &lt;source media='(min-width: 1440px)' srcset=&quot;{{ image.getUrl(thumb1440) }} 1x, {{ image.getUrl(thumb1440_2x) }} 2x&quot;&gt;
    &lt;source media='(min-width: 1280px)' srcset=&quot;{{ image.getUrl(thumb1280) }} 1x, {{ image.getUrl(thumb1280_2x) }} 2x&quot;&gt;
    &lt;source media='(min-width: 1024px)' srcset=&quot;{{ image.getUrl(thumb1024) }} 1x, {{ image.getUrl(thumb1024_2x) }} 2x&quot;&gt;
    &lt;source media='(min-width: 768px)' srcset=&quot;{{ image.getUrl(thumb768) }} 1x, {{ image.getUrl(thumb768_2x) }} 2x&quot;&gt;
    &lt;source media='(min-width: 600px)' srcset=&quot;{{ image.getUrl(thumb600) }} 1x, {{ image.getUrl(thumb600_2x) }} 2x&quot;&gt;
    &lt;source media='(min-width: 412px)' srcset=&quot;{{ image.getUrl(thumb412) }} 1x, {{ image.getUrl(thumb412_2x) }} 2x&quot;&gt;
    &lt;source media='(min-width: 360px)' srcset=&quot;{{ image.getUrl(thumb360) }} 1x, {{ image.getUrl(thumb360_2x) }} 2x&quot;&gt;
    &lt;img itemprop=&quot;image&quot; src=&quot;{{ image.getUrl(thumb320) }}&quot; alt='{{ image.title }}'&gt;
&lt;/picture&gt;
</code></pre>
<p>The problem is that this is generating a lot of queries and I wanted to find out if there is a more efficient way of coding this?</p>

<craft3><image-transforms><performance>
Craft CMS images transform srcset sizes
# Craft CMS images transform srcset sizes

(Asked by: username_0 on 2022-02-21)

I'm new to craft cms and I'm trying to generate srcset sizes for an image with the following code.
{% set thumb320 = { width: 320, format: 'jpg' } %}
{% set thumb320_2x = { width: 640, format: 'jpg' } %}
{% set thumb360 = { width: 320, format: 'jpg' } %}
{% set thumb360_2x = { width: 640, format: 'jpg' } %}
{% set thumb412 = { width: 414, format: 'jpg' } %}
{% set thumb412_2x = { width: 828, format: 'jpg' } %}
{% set thumb600 = { width: 600, format: 'jpg' } %}
{% set thumb600_2x = { width: 1200, format: 'jpg' } %}
{% set thumb768 = { width: 603, format: 'jpg' } %}
{% set thumb768_2x = { width: 1206, format: 'jpg' } %}
{% set thumb1024 = { width: 803, format: 'jpg' } %}
{% set thumb1024_2x = { width: 1606, format: 'jpg' } %}
{% set thumb1280 = { width: 1003, format: 'jpg' } %}
{% set thumb1280_2x = { width: 2006, format: 'jpg' } %}
{% set thumb1440 = { width: 1120, format: 'jpg' } %}
{% set thumb1440_2x = { width: 2240, format: 'jpg' } %}
{% set thumb1600 = { width: 1224, format: 'jpg' } %}
{% set thumb1600_2x = { width: 2448, format: 'jpg' } %}
{% set thumb1920 = { width: 1244, format: 'jpg' } %}
{% set thumb1920_2x = { width: 2488, format: 'jpg' } %}
{% set thumb2560 = { width: 1368, format: 'jpg' } %}


    
    
    
    
    
    
    
    
    
    
    


The problem is that this is generating a lot of queries and I wanted to find out if there is a more efficient way of coding this?

**Tags:** craft3, image-transforms, performance


---

## 1 answers

### Answer by username_1 on 2022-02-22. Score: 7 | Accepted answer

You can use the method Asset::getSrcset to generate a valid srcset attribute as well as the asset transforms included in it. But you will need to restructure your HTML a bit. The current approach works, but is very verbose and not optimal for different screen resolutions and image placements.
Instead of using multiple source, just use one source without a media attribute that includes all variants in its srcset. Then add a sizes attribute that will tell the browser how large the image will be displayed depending on the viewport width. If the image always spans the full page, you can just set your sizes attribute to 100vw (100 viewport width units). If your image is sized differently depending on the viewport, you will need to adjust the sizes attribute to match those sizes. Here's a great article on MDN on responsive images, including how to use the sizes attribute.
Now the final code can look like this:

    
    


The great thing about this approach is that browsers will take care of adjusting for pixel density for you. If you open the page with this image on a smartphone with a 360px wide display (CSS pixels) and a 2x display density (so a 720px screen), the browser will automatically select the 768px image, since it's the smallest available size that's large enough for the screen's resolution and density.
Note that as per the spec browsers may select images based on other factors, such as using a smaller images if network conditions are poor, or using a cached image even if it's smaller than the currently required resolution. But in practice this rarely matters.
By the way, with the code above, you can very easily add a second  with the same srcset and sizes attributes but using type image/webp and format: 'webp' in the transform to generate WebP variants of the images for browsers that support it. This will have a large impact on web performance.

> **Comments:**
> **username_0**: Perfect thank you a lot for helping me. I take the opportunity to ask you how precise you are in determining the various image sizes and how many you usually generate (for how many resolutions)?  
> **username_0**: I have noticed that by using imagerx there are significant performance improvements (a lot less database queries). Do you use such a plugin for responsive images?  
> **username_1**: @username_0 Most of our projects have containers with fixed widths (per viewport) and a multi-column layout (using Bootstrap, for example), so we have ~6 different fixed sizes in pixels – though it depends on the image positioning. For an image that stretches the whole viewport, there's only a single size. Then we generate the srcset with those sizes as well as some others for different pixel densities. You can't get every size in every possible resolution, that would be hundreds of images, so we usually just 'fill in the gaps' between sizes so that most devices will find a suitable image.  
> **username_1**: @username_0 We don't use a plugin, the built-in image resizer works just fine for us. The resizing is a one-time operation for each placed image, after all, and the HTML output can be cached, avoiding excessive queries for most requests. BTW we have a reusable twig template to take care of this stuff, every other template just includes that template and passes it an image, the `sizes` attribute and the list of sizes for the `srcset`. I've written a bit about that here: https://craftcms.stackexchange.com/a/38383/11705  
> **username_0**: Great! thank you so much for your valuable answers  

---

