I have been working on a project to develop a website. I want to use the 'srcset' attribute to apply different sizes of images on different devices. Here's how I define my image in the code:
<img
srcset="images/mobile/image-header-750w.jpg 750w,
images/desktop/image-header-2880w.jpg 2880w"
sizes="(max-width: 767px) 750w,
2880w"
src="images/desktop/image-header-2880w.jpg"
alt=""
class="header-banner">
But the browser is not detecting the mobile image which has 750px width.
Anyone knows why is this happening?
You must set "width descriptor" in srcset (aka w) and expected width in sizes (aka px, em, rem...).
<img
srcset="images/mobile/image-header-750w.jpg 750w,
images/desktop/image-header-2880w.jpg 2880w"
sizes="(max-width: 767px) 750px, 2880px"
src="images/desktop/image-header-2880w.jpg"
class="header-banner">
Remember that the browser still choose which image to use depending the expected size and the density (x1 for "classic" screens, and x2 or x3 for high density display, aka retina screen).
As example, by default Safari's responsive mode use x3 density. In this configuration, in mobile mode (approx 400px wide), it still shows the 2880w image. The expected size is 750px in high density, it needs a 2250px wide image to render it at best condition. Safari will choose the closest image in the set (so 2880w over the 750w).
Related
I'm trying to use a (max-width: ...) along with a default size specification in the sizes attribute of an <img srcset...>. However, this does not work as I'd expect. I created the following test case:
<p>
<b>Viewport width</b>: <span id="width"></span><br>
<b>Device pixel ratio</b>: <span id="ratio"></span><br>
<p>
<h3>Max-width + default (break #1600)</h3>
<img
srcset="https://via.placeholder.com/1100x200 1100w,
https://via.placeholder.com/2000x400 2000w"
sizes="(max-width: 1600px) 1100px, 2000px"
src="https://via.placeholder.com/300x400" class="full-width">
<h3>Without sizes</h3>
<img
srcset="https://via.placeholder.com/1100x200 1100w,
https://via.placeholder.com/2000x400 2000w"
src="https://via.placeholder.com/300x400" class="full-width">
See my Codepen here
What I expect the browser to do is to use the low res image below a viewport width of 1600px (or 800px on a double density screen) and the high res image in all other cases. However, both Firefox 104 and Chrome 105 ALWAYS render the high res image.
I've tested this in "Responsive" mode with network caching disabled and hard reloads every time, starting from the lowest resolution to the higher one, ensuring that the high res image wasn't loaded from the start. And as you can see that only works as expected when I don't specify any sizes (in which case the browser simply switches when the viewport width exceeds the low res image width):
What am I doing wrong here and how do I get the expected behavior using the max-width specification in sizes?
Unfortunatly I do not have a retina device to test. This is my code:
<img src="http://localhost/example/wp-content/themes/example/libs/lib_cis/libs/renderer.php?src=http://localhost/example/wp-content/uploads/2017/12/dummy-960x480-Dragonfly.jpg&w=960&h=480&q=80&zc=1"
srcset="
http://localhost/example/wp-content/themes/example/libs/lib_cis/libs/renderer.php?src=http://localhost/example/wp-content/uploads/2017/12/dummy-960x480-Dragonfly.jpg&w=240&h=120&q=80&zc=1 240w,
http://localhost/example/wp-content/themes/example/libs/lib_cis/libs/renderer.php?src=http://localhost/example/wp-content/uploads/2017/12/dummy-960x480-Dragonfly.jpg&w=480&h=240&q=80&zc=1 480w,
http://localhost/example/wp-content/themes/example/libs/lib_cis/libs/renderer.php?src=http://localhost/example/wp-content/uploads/2017/12/dummy-960x480-Dragonfly.jpg&w=960&h=480&q=80&zc=1 960w,
http://localhost/example/wp-content/themes/example/libs/lib_cis/libs/renderer.php?src=http://localhost/example/wp-content/uploads/2017/12/dummy-960x480-Dragonfly.jpg&w=1440&h=720&q=80&zc=1 1440w,
http://localhost/example/wp-content/themes/example/libs/lib_cis/libs/renderer.php?src=http://localhost/example/wp-content/uploads/2017/12/dummy-960x480-Dragonfly.jpg&w=1920&h=960&q=80&zc=1 1920w"
sizes="(min-width:960px) 960px,100vw"
alt="Animal X">
Normal screens always choose the correct image as expected (tested). However I wonder if a retina device (with a resolution of 1.5x or 2x) will choose the correct image for theme?
e.g. A retina screen with 1200px in the Browser window should choose the 1920w image, not the 960w image.
Yes it will. It does calculation based on your image width and screen size and then checks with the dpi.
In your example:
1440/1200 = 1.2
1920/1200 = 1.6
So if the screensize is 1200px and non-retina it will choose the first as it's closest to 1 (non-retina). If it's retina 1.5x or 2x it will choose the second as 1.6 is close to 2.
When you use a srcset attribute in your image tag, you can add the corresponding device pixel ratio after each file (seperated from the filename by a space and followed by a comma), which will define which image is suitable for which screen. So that would for example be
<img srcset="small_image.jpg 1x, medium_image.jpg 2x, large_image.jpg 3x" src="default_image.jpg" alt="whatever">
(the regular src attribute following srcset is used by browsers which can't handle srcset)
I have a web page design where the layout size and image sizes are based on em's. For example:
<html style="width:50em; font-size:16pt">
<body>
<p>Lorem ipsum
<img src="..." style="float:right; width:20em">
</p>
</body>
</html>
Because the image size is specified in em's, it is always in lockstep with the text size. Unfortunately, we don't know how many CSS pixels wide an image is. We also don't know how many device pixels wide an image is, which depends on the size of an em, the magnification, etc.
The <img> srcset and sizes attributes appear to be nearly the solution I want. But I'm not sure if it applies to my situation here. I can generate multiple asset sizes, e.g. 320×240, 480×360, 640×480, etc.
I want the web browser to look at the content box for the <img> element, calculate how many device pixels wide it is, and download the most appropriate image from a list of alternatives. How can I do this?
Note: I did read about the srcset x syntax, but it doesn't seem to be the right tool.
Srcset is definitely a great way to approach this. You basically have a number of images you save out for multiple sizes, usually you'll want to have the image be the same width of the element if possible. Then you set the image that you want to use for each screen width.
<img src="image.jpg" alt="Name"
srcset="
/img-2400.jpg 2400w,
/img-1800.jpg 1800w,
/img-1200.jpg 1200w,
/img-900.jpg 900w,
/img-600.jpg 600w,
/img-400.jpg 400w"
sizes = "(min-width: 2400px) 900px,
(min-width: 1800px) 600px,
(min-width: 1200px) 500px,
(min-width: 900px) 500px,
(min-width: 600px) 600px,
400px" />
So /img-2400.jpg 2400w would use /img-2400.jpg when the screen is closest to 2400px wide.
In the sizes attribute, you can also specify if what the image size will be at certain screen sizes as it may not always be 100% of the width of the browser.
So (min-width: 2400px) 900px is telling the browser that when the window is at least 2400px wide, the image will be 900px wide on the screen. So that should be telling the browser to then grab /img-900.jpg when the window is 2400px wide since that image is set to 900w which is the closest to 900px (its exact).
You can still approximately calculate this if you are using em, by multiplying the em you are using by 16 (this may vary depending on browser settings or settings you impose in your css). So if you set your width of an image in css to be 20em, thats 16 * 20 = 320px.
When these are used in combination, modern browsers should be able to detect the best image to grab dependent on the screen size. See browser compatability for srcset here: https://caniuse.com/#search=srcset
Based on Eric Portis's article, this solves the problem:
<img style="width:20em" sizes="20em"
src="pic-1000.png"
srcset="
pic-150.png 150w,
pic-220.png 220w,
pic-330.png 330w,
pic-470.png 470w,
pic-680.png 680w,
pic-1000.png 1000w">
After the web page is loaded, if the most appropriate image changes for some reason (e.g. using zoom to change the device pixel ratio), then Firefox will always change the image to the most appropriate one at the moment. By contrast, Chrome seems to change the image if the new one is bigger, but won't change to a small image unless you reload the page - the image resolution is sticky upwards.
I understand that the srcset is used to determine which image to load based on the dpi of the device. I came across this example on the Google Web Fundamentals which seems to use the w unit along with the vw unit which just happens to be the 1 % ofviewport width:
<img src="lighthouse-200.jpg" sizes="50vw"
srcset="lighthouse-100.jpg 100w, lighthouse-200.jpg 200w,
lighthouse-400.jpg 400w, lighthouse-800.jpg 800w,
lighthouse-1000.jpg 1000w, lighthouse-1400.jpg 1400w,
lighthouse-1800.jpg 1800w" alt="a lighthouse">
Help me understand what the unit of measure for this is and how I can use it?
According to MDN the w refers to:
a width descriptor (a positive integer directly followed by w).
The width descriptor is divided by the source size given in the sizes
attribute to calculate the effective pixel density.
Additionally, the W3 states:
The user agent will calculate the effective pixel density of each
image from the specified w descriptors and the specified rendered size
in the sizes attribute. It can then choose any of the given resources
depending on the user’s screen’s pixel density, zoom level, and
possibly other factors such as the user’s network conditions.
If the user’s screen is 320 CSS pixels wide, this is equivalent to
specifying wolf-400.jpg 1.25x, wolf-800.jpg 2.5x, wolf-1600.jpg 5x. On
the other hand, if the user’s screen is 1200 CSS pixels wide, this is
equivalent to specifying wolf-400.jpg 0.33x, wolf-800.jpg 0.67x, wolf-1600.jpg 1.33x. By using the w descriptors and the sizes
attribute, the user agent can choose the correct image source to
download regardless of how large the user’s device is.
Example 13 on the W3 page provides additional detail.
w is the intrinsic width of an image. It's the number you get when you right click the image and select Get Info on Mac, or Properties on Windows.
Why do you need to specify w? Because the first value of the srcset attribute only points to the link to load the image. It says nothing about the width of an image. The browser can't tell the dimension of an image until it has actually been loaded.
And why does the browser need to know the intrinsic width of an image?
Here is what browsers do when loading an image:
look at its device width
look at sizes and figure out which image size will be best to choose
look at the reference list in srcSet and choose the image whose size matches, or is bigger than the number above.
To borrow the sample code from MDN:
<img srcset="elva-fairy-480w.jpg 480w,
elva-fairy-800w.jpg 800w"
sizes="(max-width: 600px) 480px,
800px"
src="elva-fairy-800w.jpg"
alt="Elva dressed as a fairy">
A common practice is include the intrinsic image width in the image path. However, there is nothing that stops you from lying like this:
<img srcset="elva-fairy-480w.jpg 600w,
elva-fairy-800w.jpg 800w"
sizes="(max-width: 600px) 480px,
800px"
src="elva-fairy-800w.jpg"
alt="Elva dressed as a fairy">
This means that if a browser with a viewport width of 480px loads the page, the max-width: 600px condition will be true, and the browser has a slot of 480px wide to load image.
The image elva-fairy-480w.jpg will be loaded, as its intrinsic width (600w - inflated!) is closest to the slot size.
So there is probably no harm if you overstate the intrinsic width of your image.
What if you understate the intrinsic width?
<img srcset="elva-fairy-480w.jpg 280w,
elva-fairy-800w.jpg 800w"
sizes="(max-width: 600px) 480px,
800px"
src="elva-fairy-800w.jpg"
alt="Elva dressed as a fairy">
On a viewport width of 480px, the image elva-fairy-800w.jpg will be loaded instead because elva-fairy-480w.jpg is reported to be 280w and doesn't meet instruction in sizes.
So understating the intrinsic width of an image will result in the browser loading an overly large image, which defeats the very purpose of responsive iamges.
I haven't thought through all the ramifications from lying about the image's intrinsic width though.
I want to know how could I start using the HTML srcset img attribute in my mobile apps. Or Is there any other jQuery plugin which helps me to solve image resolution problem.
<img srcset="banner-HD.jpeg 2x, banner-phone.jpeg 100w, banner-phone-HD.jpeg 100w 2x" alt="Banner Image" />
In short, Srcset is a new attribute which allows you to specify different kind of images for different screen-sizes/orientation/display-types. The usage is really simple, you just provide a lot of different images separating them with a comma like this: <img src="image.jpg" alt="image" srcset="<img> <descriptor>, ..., <img_n> <descriptor_n>">. Here is an example: srcset="image.jpg 160w, image2.jpg 320w, image3.jpg 2x"
This is a longer answer which explains things in more details.
Difference between srcset and picture. Both srcset and picture does approximately the same things, but there is a subtle difference: picture dictates what image the browser should use, whereas srcset gives the browser a choice. A lot of things can be used to select this choice like viewport size, users preferences, network condition and so on. The support for srcset is pretty good and almost all current browsers more or less support it. Situation with a picture element is a little bit worse.
Descriptors are just a way to show what kind of image is hidden behind the resource. There are various kinds of descriptors:
density descriptor. srcset="image.jpg, image-2X.jpg 2x"
The display density values—the 1x, 2x, etc.—are referred to as display density descriptors. If a display density descriptor isn’t provided, it is assumed to be 1x. Good variant to target retina displays.
width descriptor. srcset="image-240.jpg 240w, image-640.jpg 640w". I am sure this is self explanatory. The only problem is that by itself width descriptor is not really helpful. Why? read here
size descriptor, which only makes sense if you use width descriptor. srcset="image-160.jpg 160w, image-320.jpg 320w, image-640.jpg 640w, image-1280.jpg 1280w" sizes="(max-width: 480px) 100vw, (max-width: 900px) 33vw, 254px">. The instructions for the browser would look like this: (max-width: 480px) 100vw — if the viewport is 480 pixels wide or smaller, the image will be 100% of the viewport width. (max-width: 900px) 33vw — if the viewport is 480 pixels wide or smaller, this rule will never be reached because of the previous media condition. And 254px is when there is no media condition listed, the length is assumed to be a default value used when none of the other media conditions are met.
Just for completeness will add here that there is an image-set() attribute for a background image in CSS and some other helpful link here
Here is a detailed guide on srcset along with code samples.
srcset allows you to define a list of different image resources along with size information so that browser can pick the most appropriate image based on the actual device’s resolution.
Each comma-separated item in srcset has:
Image URL, e.g. http://ik.imagekit.io/demo/default-image.jpg or relative path /demo/default-image.jpg
An empty space
The actual width of the image or display density:
Either using display density descriptor, for example, 1.5x, 2x etc.
Or, using width descriptors, for example, 450w. This is the width of the image in pixels.
Using display density descriptor
The syntax for display density descriptors is straightforward. srcset provides a comma-separated list of image resources along with display density it should be used, for example1x, 2x etc.
<img src="image.jpg"
srcset="image.jpg,
image_2x.jpg 2x"
/>
Live demo - https://imagekitio.github.io/responsive-images-guide/srcset-density.html.
Using width descriptor
The syntax is similar to the display density descriptor, but instead of display density values, we provide the actual width of the image.
<img src="image.jpg"
srcset="small.jpg 300w,
medium.jpg 600w,
large.jpg 900w"
/>
This lets the browser pick the best image
Using width descriptor allows the browser to pick the best candidate from srcset based on the actual width needed to render that image on that particular display at runtime.
Note that display pixel density is also taken into account by the browser while calculating the required width. 😎
For example, assuming an image takes up the whole viewport width - On a 300px wide screen with DPR 2, the browser will pick medium.jpg because it needs a 300x2=600px wide image. On a 300px wide screen with DPR value 3, the browser will select large.jpg because it needs a 300x3=900px wide image.
Demo - srcset with width descriptor
Let see this in action with a live demo - https://imagekitio.github.io/responsive-images-guide/srcset-width.html.
Here is a good article on the srcset attribute and how to use it. srcet allows you to declare a set of images to be displayed on different viewport sizes. You just have to save and image at different resolutions e.g. banner-phone-HD.jpeg would be the highest resolution.
Exmaple:
<img alt="my awesome image"
src="banner.jpeg"
srcset="banner-HD.jpeg 2x, banner-phone.jpeg 640w, banner-phone-HD.jpeg 640w 2x">
The above would serve banner-phone.jpeg to devices with viewport width under 640px, banner-phone-HD.jpeg to small screen high DPI devices, banner-HD.jpeg to high DPI devices with screens greater than 640px, and banner.jpeg to everything else.
There are also other methods like CSS media queries you can use to produce the same effect.
I am not aware of any JQuery plugins which would help with this.