When loading an image, historically I loaded the largest size of the image that would be used.
e.g. example.jpg
is an 1170px wide image for large screens. On small screens this big image is loaded but scaled down to display properly.
The important thing to note here is even if the image is only displaying at 400px wide, the load time and bandwidth used are based on the size of the full 1170px wide image.
<src="images/example.jpg" alt="Example">
This can be improved with the srcset
attribute (pronounced “source set”).
Backwards Compatibility
If an attribute, like srcset
, is not recognized by a browser it is ignored. This fact allows us to use srcset
freely since older browsers will ignore srcset
and use src
instead. For this reason, we include the src
attribute pointing to the large image just as we have in the past.
srcset on Modern Browsers
If a browser does support srcset
, the browser will intelligently load one of the images listed.
Note I use lots of whitespace to make the markup easier to read.
<img srcset="
images/example-300x300.jpg 300w,
images/example-768x768.jpg 768w,
images/example-1024x1024.jpg 1024w,
images/example.jpg 1170w"
src="images/example.jpg"
alt="Example">
There are multiple image definitions in srcset and they are separated by commas (,
). Each image definition is made up of two parts and separated by one or more spaces:
- the URL for the image
- the width of the image in px (e.g.
300w
is300px
)
When loading, the browser uses the width of its own window as a guide to choosing the smallest version of the image that is at least as wide as the browser window.
For example, if our browser window is 700px wide, the 768w
image will load (images/example-768x768.jpg
) because it is the smallest width that is equal to or bigger than the browser window (700px).
Examples
Browser Window Width | likely image size loaded† |
---|---|
1500 | 1170w |
800 | 1024w |
400 | 768w |
300 | 300w |
300 with 2x pixel density* | 768w |
* High Pixel Density Screens Impact our Calculations
† See “Why Likely Image Size Loaded?” below
High Pixel Density Screen
Some devices have High Pixel Density Screens, e.g. the Mac Retina series. For these high pixel density screens, it is common to have double the number of vertical and horizontal pixels (a 2x
display). A 2x
display means a 320x568
screen can display 640x1136
pixels. Some higher pixel density devices display 3x
or even 4x
resolution but for simplicity we’ll focus on 2x
here.
This 2x
density allows the browser to replace a 300x300
image with a 600x600
image on a webpage and it will still appear the same size as the 300x300
but will display the image with a higher resolution.
In the example chart above, a browser width of 300px on a 2x
screen can accommodate a 600px wide image so the 768w
would be the size most likely chosen by the browser.
While this can get confusing, don’t get hung up on it. The browser does all the hard work of choosing which size to display. You list the different image URLs and their widths in the srcset
attribute and the browser determines the best image size and loads it.
Why Likely Image Size Loaded?
I say “likely image size loaded” because choosing the most appropriate image to load is a decision left up to the browser. As of this writing, browsers determine the smallest image that properly fits in the area but it is likely we’ll see more advanced behavior from browsers in the future. For example, I can imagine in the future a browser on a mobile device with a slow connection may choose smaller image sizes to save bandwidth and speedup loading.
Sizes Attribute (Not all Images are the Full Screen Width)
You may have noticed, we refer to the browser window width when determining what size image to load. Wouldn’t it make more sense to load an image based on how big it is displayed on the page. For example, if an image takes up only half the width of the page shouldn’t we use that size when deciding which image to load.
The problem here is we want to start loading the image right away (i.e. we don’t want to wait for the CSS to load and be applied first). In many cases the CSS being applied to the page affects the size an image is ultimately displayed.
In other words we need more information when choosing our image and this information comes in the form of the sizes
attribute.
For example if we assume our example.jpg
will be displayed in half the width of the page we can use sizes="50vw"
(which indicates 50% of the viewport width).
Now our code looks like this
<img srcset="
images/example-300x300.jpg 300w,
images/example-768x768.jpg 768w,
images/example-1024x1024.jpg 1024w,
images/example.jpg 1170w"
sizes="50vw"
src="images/example.jpg"
alt="Example">
Media Queries and the Sizes Attribute
If you’re a big fan of Bootstrap like me, you may have the problem where your image takes up half the width of the page (6 of the 12 grid columns) but on narrow screens the grid collapses and the images become full width. For me this collapse occurs below 768px
. We can modify our sizes
attribute to accommodate for this with:
sizes="(min-width: 768px) 50vw, 100vw"
This says for any screen widths 768px
or greater our image will take up 50% of the horizontal view port. Otherwise our image will take up 100% of the horizontal view port.
Including the sizes
attribute allows you to refine how sizes are chosen.
Our final code looks like
<img srcset="
images/example-300x300.jpg 300w,
images/example-768x768.jpg 768w,
images/example-1024x1024.jpg 1024w,
images/example.jpg 1170w"
sizes="(min-width: 768px) 50vw, 100vw"
src="images/example.jpg"
alt="Example">
What is conclusion of this article ?
Should we disable srcset or not beacuse i think srcset increase page size ?
Hi Ashoksinh,
Thanks for your comments.
I think srcset is a great improvement to the web and should not be disabled. When you mention the increased page size, I assume you’re referring to the edge case I describe in another post. I’ve updated that post, WordPress Responsive Images Increased Page Size, to describe what I’m now doing to prevent that issue.
yes you are right, it better to use tinypng…because i see that if i upload image which size is 15 kb….wordpress resize in another image so badly that image size become 30 kb …(specifically where your image size is not set as thumbnail,mediaum or small- if you made your custom dimention)
..after your suggestion i use tinypng plugin and now all image that size is 32 now become 8 kb….it cool …my webpage size reduce by 130 kb..thanks
Great explanation about
srcset
! One question that I was left with is about this statement:Does WordPress natively handle this, or do you have to filter WordPress’ output to include the sizes attribute?
Hi JPry,
I’m glad you enjoyed this post. Regarding WordPress’s use of srcset and the
sizes
attribute, it uses the wp_calculate_image_sizes() function to generate the values for thesizes
attribute. This function uses a safe default forsizes
, which looks something likewhere
1024px
is the width of the WordPress image size you are using (e.g. The large size is 1024px wide by default).Generally, it isn’t worth modifying this value but if you really want to you can use the
wp_calculate_image_sizes
filter.I’ve written another post specifically about responsive images in WordPress, that might be of interest as well. I’ve now added a link to that post in the content.
Hi Sal – great article. Do you have any tips on customizing Genesis child themes so they take advantage of srcset functionality? I’m thinking there should be some default setting to enable, but I cannot find one. I’ve tried writing some code that uses wp_calculate_image_sizes, but that seems to be overridden by Genesis and doesn’t work.
Any tips you have are greatly appreciated!
Hi Patrick,
WordPress tries to automatically add
srcset
values wherever it can. I have more details about how WordPress does this in my WordPress Responsive Images post. I’ve found that by leveraging WordPress functions like the_post_thumbnail(), I can get thesrcset
values without doing any extra work. I’d be interested to hear more about which Genesis child theme you’re using and in what context you’re not gettingsrcset
values. If there is way to improve this in Genesis, I know the team would love to hear about it.