I am adding a image to my site that will need to be different dimensions based on the resolution of the screen (pretty common).
What is tripping me up however, is the images that I have set in <img srcset="X"> are not changing at the given widths.
(quick note, I use incogento in chrome so this is not the FAMOUS cache issue)
anyway - on with the show:
Several images (specifically sized)
HTML CODE:
<img src="im2/1280.jpg"
srcset="im2/120.jpg 120w,
im2/320.jpg 320w,
im2/640.jpg 640w,
im2/1280.jpg 1280w,
im2/1920.jpg 1920w"
sizes="(max-width: 250px) 120px,
(max-width: 480px) 320px,
(max-width: 720px) 640px,
(max-width: 1400px) 1280px,
(max-width: 2000px) 1920px,
"
alt="Image description">
So based on my above code I would expect that the first image would be 120.jpg (if the screen was under 250px wide) - however:
First is 320px
at 460px it shows the image for 1280px
My guess is that I have missed some key bit of info on how this works.
if anyone can shed some light on this that would be great.
Thanks in advance -
Wally
A great article to read about this topic can be found here (its next level at explaining how the picture and srcset tag should be used)
https://alligator.io/html/picture-element/
Short answer is that images tags <img> that use srcset <img srcset="X"> will be given a width of the image for the browser to decide what to do with <img srcset="X.jpg 200w">
BUT IT IS THE BROWSER that decides what image to use based off the values given.
I.e.
<img srcset="X.jpg 1000w">
The browsers might use that on a display that is 400px wide
For specific images to be used at specific screen sizes then refer to the linked article which gives all the info required.
Related
When using the wp_get_attachment_image() function in WordPress, by default it outputs a value in the 'sizes' attribute of the img tag. This sizes attribute tells the browser which thumbnail size of the image to load.
The value seems to be related to the largest image in the srcset attribute. So:
an image with dimensions of 2509x1673 gets: sizes="(max-width: 2509px) 100vw, 2509px"
an image with dimensions of 768x512 gets: sizes="(max-width: 768px) 100vw, 768px"
But this only works right when the image is being displayed over the full width of the browser window. If the image is shown in one column of a grid, the browser should be loading a much smaller version of the image.
So I overwrite the sizes attribute like this:
echo wp_get_attachment_image( $term_image, $term_image_size, false, array('sizes' => '(max-width: 575px) 258px, (max-width: 991px) 330px, 436px'));
But this feels like an absolute hassle. I understand that the server and/or WordPress are not able to decide what the sizes attribute needs to contain upon generating the DOM, because it doesn't take the CSS into consideration. But since WordPress also adds loading="lazy" to the markup, the image isn't being loaded directly in most cases. So maybe there are chances to change this on beforehand?
There should be a better way than manually filling the sizes attribute. Does anyone have any tips?
How does the srcset attribute determine the correct image in conjunction with the sizes attribute? Take this image for example:
<img alt="Demo image"
sizes="(min-width: 1024px) 512px,
100vw"
srcset="img/banner-large.jpg 2048w,
img/banner-medium.jpg 1400w,
img/banner-small.jpg 800w">
(I cleared the cache in Chrome)
I thought that the last image would always be chosen (800w), because of the 512px (sizes) and the image width of 800w (srcset), but that image did not always get selected? Why?
Here is a detailed guide on using Srcset with sizes.
sizes attribute contains a comma-separated list. Each item in the list describes the size of the image in relation to the viewport.
Using the sizes attribute with srcset provides the browser with enough information to start downloading the right image as soon as it sees an <img> tag in HTML without waiting for styles sheets to complete downloading and parsing.
Why do we need sizes?
If you are wondering why the browser is not aware of how big the image will render, checkout how the browser loads a web page.
The syntax:
<img src="image.jpg"
srcset="small.jpg 300w,
medium.jpg 600w,
large.jpg 900w"
sizes="(max-width: 300px) 100vw, (max-width: 600px) 50vw, (max-width: 900px) 33vw, 900px"
/>
Each comma-separated item in sizes has:
Media conditions, for example, (max-width: 300px) - It describes a possible state that the screen can be in. (max-width: 300px) means when the viewport width is 300 CSS pixels or less. It is similar to media queries but with some limitations. You cannot use screen or print.
An empty space.
The width of the image element when the media condition is true. You can provide an absolute length (px, em) or a length relative to the viewport (vw), but not percentages.
Demo - srcset with sizes
Let’s see this in action with a live demo - https://imagekitio.github.io/responsive-images-guide/srcset-sizes.html
The layout is such that:
If viewport width is above 900px, each image takes a fix 225px width.
Upto 900px, each image takes up 33vw i.e. 33% width of total viewport width.
Upto 700px, each image takes up 50vw i.e. 50% width of total viewport width.
Upto 400px, each image takes up 100vw i.e. the whole viewport width.
HTML markup of a single image element looks like this:
<img src="https://ik.imagekit.io/ikmedia/women-dress-1.jpg"
srcset="https://ik.imagekit.io/ikmedia/women-dress-1.jpg?tr=w-225 225w,
https://ik.imagekit.io/ikmedia/women-dress-1.jpg?tr=w-300 300w,
https://ik.imagekit.io/ikmedia/women-dress-1.jpg?tr=w-350 350w,
https://ik.imagekit.io/ikmedia/women-dress-1.jpg?tr=w-640 640w"
sizes="(max-width: 400px) 100vw, (max-width: 700px) 50vw, (max-width: 900px) 33vw, 225px">
Let’s see what happens at different screen size and DPR values -
The sizes attribute determines the media condition that applies to the current device width (the first media condition that applies is selected). Then, the browser checks the srcset attribute to find the image that most closely matches the slot size determined by the sizes attribute. Note that the browser chooses a larger image for high-res displays like Retina (usually chooses an image close to double the width it would choose on a "normal" resolution display). See Responsive images and Responsive images: If you're just changing resolutions, use srcset for a lot more detail on how this works.
So in your case, you would expect to get the banner-small.jpg image on a "normal" resolution device where device width is at least 1024px (and you would also expect to get that same image on smaller width "normal" resolution devices due to the larger widths of your other srcset image options).
Some reasons that you might not get the results you expect:
Older browser versions don't support srcset
Did not specify <meta name="viewport" content="width=device-width"> to force devices to adopt their real width when loading the page.
Browsers may display cached images rather than selecting the closest size match from srcset (as you noted in your question).
When attempting to display multiple sizes of the same image on a page, browsers may download only the largest image needed and use it in each instance (rather than downloading multiple images).
If you are attempting to test image selection behavior in some sort of sandboxed iframe environment like jsfiddle, it is difficult to be sure that the browser is interpreting the size of the display pane as "device width" (I have had mixed results with srcset in these types of environments). It seems to behave reasonably in a SO snippet for browsers like Chrome and Firefox (as long as you clear the cache). See below for an example snippet (better used in your own environment) that makes it visually obvious which image has been selected when testing.
<img srcset="https://via.placeholder.com/300x150 300w,
https://via.placeholder.com/600x300 600w"
sizes="(min-width: 1024px) 600px,
100vw"
src="https://via.placeholder.com/300x150"
alt="placeholder image">
I've been working hard on trying to get responsive images working on this website I'm building and just when I thought it's going well, I look at it on the iPad retina screen and it's selecting the wrong image. Not only is it the wrong size but it's also displaying as landscape, not portrait. I have no idea why it's doing this as I've created custom image sizes for all the different screen sizes and also have created the XL version to be used on retina screens.
Here is the HTML of the image with the srcset and sizes.
<img class="scene_element scene_element--fadeinup" src="http://localhost:8888/wp-content/uploads/2017/11/Westfield-House-049-March-2017-505x757.jpg"
srcset="http://localhost:8888/wp-content/uploads/2017/11/Westfield-House-049-March-2017.jpg 3684w,
http://localhost:8888/wp-content/uploads/2017/11/Westfield-House-049-March-2017-768x1151.jpg 768w,
http://localhost:8888/wp-content/uploads/2017/11/Westfield-House-049-March-2017-1010x1514.jpg 1010w,
http://localhost:8888/wp-content/uploads/2017/11/Westfield-House-049-March-2017-505x757.jpg 505w,
http://localhost:8888/wp-content/uploads/2017/11/Westfield-House-049-March-2017-415x622.jpg 415w,
http://localhost:8888/wp-content/uploads/2017/11/Westfield-House-049-March-2017-720x1080.jpg 720w,
http://localhost:8888/wp-content/uploads/2017/11/Westfield-House-049-March-2017-360x540.jpg 360w,
http://localhost:8888/wp-content/uploads/2017/11/Westfield-House-049-March-2017-293x440.jpg 293w,
http://localhost:8888/wp-content/uploads/2017/11/Westfield-House-049-March-2017-1110x800.jpg 1110w,
http://localhost:8888/wp-content/uploads/2017/11/Westfield-House-049-March-2017-455x306.jpg 455w,
http://localhost:8888/wp-content/uploads/2017/11/Westfield-House-049-March-2017-355x238.jpg 355w,
http://localhost:8888/wp-content/uploads/2017/11/Westfield-House-049-March-2017-640x600.jpg 640w,
http://localhost:8888/wp-content/uploads/2017/11/Westfield-House-049-March-2017-320x300.jpg 320w,
http://localhost:8888/wp-content/uploads/2017/11/Westfield-House-049-March-2017-2340x1258.jpg 2340w,
http://localhost:8888/wp-content/uploads/2017/11/Westfield-House-049-March-2017-1170x629.jpg 1170w,
http://localhost:8888/wp-content/uploads/2017/11/Westfield-House-049-March-2017-940x627.jpg 940w,
http://localhost:8888/wp-content/uploads/2017/11/Westfield-House-049-March-2017-555x400.jpg 555w,
http://localhost:8888/wp-content/uploads/2017/11/Westfield-House-049-March-2017-1910x1274.jpg 1910w,
http://localhost:8888/wp-content/uploads/2017/11/Westfield-House-049-March-2017-955x637.jpg 955w,
http://localhost:8888/wp-content/uploads/2017/11/Westfield-House-049-March-2017-1574x1250.jpg 1574w,
http://localhost:8888/wp-content/uploads/2017/11/Westfield-House-049-March-2017-787x625.jpg 787w"
sizes="(-webkit-min-device-pixel-ratio: 1.5) 1010px,
(max-width: 767px) 767px, (min-width: 768px) and (max-width: 991px) 415px,
(min-width: 992px) and (max-width: 1199px) 415px,
(min-width:1200px) 505px, 505px" itemprop="thumbnail" alt="Image description" >
As retina screens are double pixels i first tried adding this to the sizes to target iPads but nothing happened:
(min-width: 2048px) 1010px
The funny thing is i have an image with the dimensions of 1010px and have specified in the sizes that when it's double the pixels to use this image. Instead it's using this size: 940x627.jpg
Can anyone explain why this is happening please?
Right people, i managed to find out why the page wasn't loading the correct images. As i mentioned in my question, Wordpress by default will only load the images in the srcset with the same aspect ratio. If you want to include custom image sizes with a different ratio you need to add them via the wp_calculate_image_srcset function.
The problem with doing this, is that all custom sizes will be loaded into every images srcset and the browser will select the image based on the closest width and ratio.
Secondly, I realised that the image which Wordpress bases the aspect ratio on is the original image size rather than the custom size you load into the page. So where i had the portrait image with the custom size of add_image_size('portrait-case-study-lg', 505, 757, true); Wordpress was actually getting the aspect ratio from the original file which was 2000px x 1500px. As this had a different ratio, the image sizes i created for the portrait sizes were being ignored and instead the image with the closest aspect ratio was being chosen.
How i fixed this was to remove the function wp_calculate_image_srcsetwhich added the sizes into the srcset and instead re size the original images in Photoshop to have the same aspect ratio as the smaller images.
So for example, instead of having the custom image size of portrait-case-study-xl which was used to crop the original image file. I removed this and instead uploaded the original image at this size.
add_image_size('portrait-case-study-xl', 1010, 1514, true);
add_image_size('portrait-case-study-lg', 505, 757, true);
This means Wordpress now selects the 'portrait-case-study-lg' on different screen sizes as the aspect ratio is the same as the original.
It would good if Wordpress could allow you to remove the original image from the srcset as it now means i can't automatically the create the correct size when the client uploads an image to a page.
I want to make a media query to target just my phone. What breakpoint(s) would I use?
For instance, my body max-width is 800px wide with 2px margins. When the window is less than 800px (mobile?) i want the margins on it to be 0px (this works on my browser). Turns out that my phones screen is hi-res and therefore the width of the display never goes below 800px!
Is this because of pixel ratios?
What do I do?
The meta-view-port tag changes how websites are displayed on your phone, or other small screens that may want to 'adjust' a website for you.
Some screens, for instance - an iphone 5 - with no meta-view-port tag, will size the website to fit your screen / but like a little version of your website zoomed out. https://developer.mozilla.org/en-US/docs/Mozilla/Mobile/Viewport_meta_tag
A combination of a view-port tag, and a media-query in your styles would allow you to change your style rules depending on the screen-size. It's kinda best just to make the breaks where things get ugly and not based on the screen sizes of "Today" that will change next month.
I would suggest building from the smallest screen first and moving up as you go with styles like this:
html {
height: 100%;
background: blue;
}
#media (min-width: 400px) {
html {
background: red;
}
}
#media (min-width: 850px) {
html {
background: green;
}
}
etc.
https://jsfiddle.net/5qhmrym5/
If you already have your site built.. and you really want to target the smaller screens, you can use max-width instead of min-width - but I've found that it takes more time and energy to override styles on the way down - then it does on the way up because styles get more complex for larger screens.
#media (max-width: 850px) {
/* styles */
}
If what you want to change is margin value when viewed on mobile you should design your display for use on any screen above the mobile size, 800px wide for you, then create a media query, similar to the ones in the link commented by #Hynes, which changes just margins to 0px.
You are correct in assuming your device is 800px wide due to ratios, but it also has to do with resolution, which are similar topics here. If you imagine a sports jumbo screen, a pixel is nearly an led in size, vs a 1080px display laptop, where the pixels are nearly unobservable. Ratios and resolutions are the reasons displays are tricky to make, and why values such as em's and percentages have come to be, to bypass the differences in display. This is also a large reason of why media queries are so useful
html {
box-sizing: border-box;}
*,*:before,*:after {box-sizing: inherit;}
Try using box-sizing: border-box on your css and also percentages, this is the way I like it, but surely you will find plenty of information about it, just google it.
Found the solution: https://stackoverflow.com/a/18500871/5906166
You need to include this in your header:
<meta name="viewport" content="width=device-width, initial-scale=1">
Explanation:
Fortunately, you can specify a viewport meta tag in the <head> section
of your document in order to control the width and scaling of the
browser's viewport. If this tag has a content value of
width=device-width, the screen's width will match the device
independent pixels and will ensure that all the different devices
should scale and behave consistently.
I noticed that an image embedded into css with Data URI scheme is displayed on Retina screens with "regular" resolution. How to embed and image with resolution required by the Retina display?
I didn't try to embed a double resolution (#2) PNG into CSS, but I suspect that it would be displayed in double size, similar to regular images when size of the image is not defined.
Two images can have the same resolution but different dpi. This is the important part in retina displays, therefore, you need two versions (if you want to save some bandwith for those that doesn't have retina) of you image with different dpi's.
For further information on how to add a rule in css, and some dpi values take a look at: Retina Display Media Query.
EDIT
As pointed out by a comment from #carlos-r-balebona, bandwith will not be saved if embed the image into the CSS, as both versions will always be sent. It will only be saved if you use image URLs as only the proper one will be downloaded.
EDIT WITH EXAMPLE
OK, here's an example:
Suppose you have 2 images (data:image/png;base64,{192_dpi_encoded_image}) and (data:image/png;base64,{96_dpi_encoded_image}).
Now suppose you have a div you want to set the background image to:
<div id="a" style="width: 100px; height:100px;">
</div>
And in your css:
#media only screen
{
#a
{
background:url(data:image/png;base64,{96_dpi_encoded_image});
}
}
#media
only screen and (-webkit-min-device-pixel-ratio: 2),
only screen and ( min--moz-device-pixel-ratio: 2),
only screen and ( -o-min-device-pixel-ratio: 2/1),
only screen and ( min-device-pixel-ratio: 2),
only screen and ( min-resolution: 192dpi),
only screen and ( min-resolution: 2dppx){
#a
{
background:url(data:image/png;base64,{192_dpi_encoded_image});
}
}
The last #media with conditions will override the background image set before only if there's a retina screen present, thus, setting the large dpi image when needed.
Hope this helps.
You can just set the background size in pixels (the values should be the original dimensions divided by two, if your image has 2x resolution):
.element {
background-image: url(data:image/png;asdkfasdkf);
background-size: 25px 50px;
}