The srcset attribute of the img element helps authors adapt their sites for high-resolution displays, to be able to use different assets representing the same image.
The picture element helps authors to control which image resource a user agent presents to a user, based on media query and/or support for a particular image format.
Both these give the author control over displaying images based on the device resolution;thus making the images responsive. So what is the main difference between them?
I did find some examples on the picture element draft, but still fail to understand the difference. Here are the examples:
Using srcset attribute:
<img src="pic1x.jpg" srcset="pic2x.jpg 2x, pic4x.jpg 4x"
alt="A rad wolf" width="500" height="500">
Using picture element:
<picture>
<source media="(min-width: 45em)" srcset="large.jpg">
<source media="(min-width: 18em)" srcset="med.jpg">
<img src="small.jpg" alt="The president giving an award.">
</picture>
Both srcset and picture do approximately the same thing, 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. Hopefully in the future browsers would become smarter and smarter with selecting the appropriate image.
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.
2017 update
From http://usecases.responsiveimages.org/:
The srcset attribute
Allows authors to define various image resources and “hints” that assist a user agent to determine the most appropriate image source to display. Given a set of image resources, the user agent has the option of either following or overriding the author’s declarations to optimize the user experience based on criteria such as display density, connection type, user preferences, and so on.
The picture element
Building on srcset, this specification defines a declarative solution for grouping multiple versions of an image based on different characteristics (e.g., format, resolution, orientation, etc.). This allows the user agent to select the optimum image to present to an end-user based on the user agent's "environmental conditions", while also providing the ability to "art direct" images.
Environmental conditions are CSS media features (e.g., pixel-density, orientation, max-width) and CSS media types (e.g., print, screen).
Art direction means transforming an image to best match the space available to it. For example, a landscape image featuring dog in front of a house can be left as is on a typical desktop screen, but on a narrow portrait mobile screen, we might want to crop the sides of the house and focus on the dog.
picture uses CSS media queries, while srcset uses image candidate strings: width descriptors, e.g. 1024w, or pixel density descriptors, e.g. 2x.
Both specifications are widely supported among current browsers, with the exception of IE, old Android Browsers, and Opera mini. srcset is better supported by outdated browsers, namely Safari 7 through 9.2 See http://caniuse.com/#feat=srcset.
The relationship is described in clause 1.3 Relation to srcset of The picture Element draft. The description is somewhat vague, since it does not make it clear what it is being compared against, but for practical purposes, the W3C Editor’s draft The srcset attribute describes the design of srcset as a separate attribute (as opposite to its different role in the proposed picture element).
The two drafts are meant to address the same problems in different ways. The srcset attribute would let you specify a list of image URLs with special notations used to indicate what widths or pixels densities they are for. The picture element uses CSS media queries for the same purpose.
Related
Many sources stress the importance of including the viewport meta tag. As per Using the viewport meta tag to control layout on mobile browsers on MDN:
Narrow screen devices (e.g. mobiles) render pages in a virtual window or viewport, which is usually wider than the screen, and then shrink the rendered result down so it can all be seen at once. Users can then pan and zoom to see different areas of the page. For example, if a mobile screen has a width of 640px, pages might be rendered with a virtual viewport of 980px, and then it will be shrunk down to fit into the 640px space.
This is done because many pages are not mobile optimized, and break (or at least look bad) when rendered at a small viewport width. This virtual viewport is a way to make non-mobile-optimized sites in general look better on narrow screen devices.
However, this mechanism is not so good for pages that are optimized for narrow screens using media queries — if the virtual viewport is 980px for example, media queries that kick in at 640px or 480px or less will never be used, limiting the effectiveness of such responsive design techniques.
And as per the web.dev entry on viewport:
Many search engines rank pages based on how mobile-friendly they are. Without a viewport meta tag, mobile devices render pages at typical desktop screen widths and then scale the pages down, making them difficult to read.
Lighthouse doesn't check that width equals device-width. It also doesn't check for an initial-scale key-value pair. However, you still need to include both for your page to render correctly on mobile devices.
So, if I understand correctly, this tag is all but required: if not included, the page will be penalized by Google and mobile browsers will display the page incorrectly, ignoring media queries prepared especially for them.
Despite the above, according to the MDN page I linked to earlier, this tag "is not part of any web standard".
Why is that so?
WHATWG says in their FAQ:
Instead of ignoring what the browsers do, we fix the standard to match what the browsers do.
Therefore, given that browsers make use of this tag and depend on it, wouldn't it be in accordance with the stated goals of the WHATWG to standardize this tag?
Perhaps something along the lines of:
The use of the meta viewport tag means that the developer declares that their website is meant to be displayed also on devices whose screen size and/or resolution significantly differs from typical desktop sizes and resolution. Without it mobile browsers should assume that the page is not meant to be displayed on them and are free to apply heuristics that may break the developers' assumptions about how their site should work (for example, they may ignore media queries and render the page at artificially large widths only to downscale it just before displaying).
Why is the viewport meta tag not included in the HTML specs? Is there any rationale available?
There is no such thing as a meta viewport tag. viewport is a setting of name which is an attribute of the meta tag.
<meta> is the tag, not viewport.
name then, according to the standard, indicates
Metadata content is content that sets up the presentation or behavior
of the rest of the content
Indeed, viewport is not a standard metadata name:
https://html.spec.whatwg.org/dev/semantics.html#standard-metadata-names
As far as I understand, the reason is that nobody has really pressed to make it a standard name (yet). Moreover, there is no pressure to make it a standard name since:
[next section: other names]
"Anyone can create and use their own extensions to the predefined set of metadata names. There is no requirement to register such extensions."
Would it be good if it was a standard name? Of course. It is annoying that something crucial like that is not a standard name.
But actually it is part of the html standard in a broader sense (other names of meta tags). I guess.
What the specification says about cases when the same path (or probably the same sized images) appear with different pixel density descriptors?
The following example renders differently in desktop (Windows) Firefox 82.0b2 and Chrome 85.0.4183.121. The image appears natively scaled in FF and half the size in Chrome
<html><head></head>
<body>
<img src="testpicture.jpg" srcset="testpicture.jpg 2x">
</body>
</html>
The reason I'm asking is because a commercial CMS I use very often uses such output. In order to encourage them to avoid this I need a clarification. In this CMS the rendered content works mostly properly in FF, but in Chrome the rendering is sometimes unexpectedly scaled or some image content not appears at all (probably relating to cache availability of different sizes).
Update: This is very likely a chromium issue when the browser due to internal logic related to caching chooses a wrong variant. But until it finally fixed, I'd rather not post my own answer
The srcset attribute is a feature that enable responsive images. Specifically srcset gives the browser a hint what resolution images are available. In your case there is only on definition which hints at one image (testpicture.jpg) which has double (2x) resolution. But since there is only one definition, the srcset attribute won't do nothing and could be omited.
A full example would look like this:
<img src="/files/16864/clock-demo-200px.png"
alt="Clock"
srcset="/files/16864/clock-demo-200px.png 200w,
/files/16797/clock-demo-400px.png 400w"
sizes="(max-width: 600px) 200px, 50vw">
Check out the MDN documentation for the image element and their guide on responsive image for further details.
As far as I can tell, the srcset and sizes attributes focus more on applying a suitably scaled image for the device’s size and resolution.
There appears to be no facility to use these attributes to select an alternative image based on the screen size, such as one cropped or oriented differently.
Is this a correct understanding of the situation? Does that mean we will have to wait for the picture element to be widely supported for this task?
You are correct that srcset and sizes are only there to provide different resolution alternatives to the "same" image - there's no guaranty which resource will be picked.
If you want to provide cropped or proportionally different alternatives that are guarantied to match your responsive breakpoints, then <picture> is what you're looking for.
As far as support goes, <picture> is fully supported in Chrome and Firefox, soon to be supported in MS Edge, and not yet supported in Safari 9.
In the mean time, you could use picturefill to add that support to non-supporting browsers.
Personally, I have used the w-descriptors and srcset to display a variety of images based on the width of the available space.
It might seem rather crude but it works for me - I edit the image so that it becomes "art-directed" for a number of common breakpoints - turning it into effectively a number of different images.
Then, based on the size of the agent's screen, the browser will almost always choose the image which I have previously determined to be the most suitable.
For my approach, I did not use size, picture or any other property.
A code as simple as this appears to work:
<img srcset="room-and-person.jpg 3200w, person-face-only.jpg 1600w" src="image.jpg" alt="an image" />
I'm seeing a lot of inconsistencies with srcset attribute on img tags (responsive images) in Chrome 40.0.2214.91
Before I updated to Chrome v40 (I was on ~39), srcset attribute worked fine and would swap the image upon browser resize. Now, sometimes, the smaller version of the image will display if I have the browser set to the desired width then refresh the page. Other times it will not work whatsoever.
Testing jsbin:
http://jsbin.com/hulaconake/1/edit?html,output
Image tag I have:
<img srcset="http://placehold.it/300x200 300w, http://placehold.it/500x400 500w">
I'm also testing this in another env with non-Placehold.it images, and using Picturefill.js http://scottjehl.github.io/picturefill/
I'm not having any issues in FF or Safari (both using picturefill).
iOS Chrome has similar problems.
Is my syntax wrong? Is there something going on I don't know about?
It's a feature not a bug. Chrome does not switch the size because Chrome already has a larger image in cache, so there is no need to download new data of the same image.
In case you want to use different images or same image with different crops, use the picture element.
Responsive images can be technically differentiated between 2 types.
srcset with source descriptors (let the browser choose the right image based on screen size/resolution, bandwidth…):
density descriptor (x) (for static image sizes, Retina vs. normal resolution)
width descriptor (w) and the corresponding sizes attribute (for flexible, responsive / adaptive images (automatically also includes Retina optimization)
and the picture element with its source[media] children (gives the author control about what srcset should be chosen by the browser depending on specific media queries)
So img[srcset] is for resolution switching and picture is for different images reacting to your design
We had an approach to use the srcset attribute to provide not only a different resolution but also a different image section within a responsive design. The alternative image url was associated with "320w" in order to show only on smartphones in portrait mode.
Since Chrome is now supporting srcset it turns out that the browser always chooses the small image regardless of the actual viewport, probably due to its lower filesize. Does that mean we have to resort to other attributes and javascript again?