To the extent possible under law, the editors have waived all copyright and related or neighboring rights to this work. In addition, as of 11 February 2014, the editors have made this specification available under the Open Web Foundation Agreement Version 1.0, which is available at http://www.openwebfoundation.org/legal/the-owf-1-0-agreements/owfa-1-0. Parts of this work may be from an existing specification document. If so, those parts are instead covered by the license of the existing specification document.
This document describes a proposed syntax for "responsive images", which allows a user agent to choose an appropriate version of an image from several candidates.
This is an unofficial draft. It is provided for discussion only and may change at any moment. Its publication here does not imply endorsement of its contents by W3C. Don’t cite this document other than as work in progress.
The Responsive Images community has been trying for some time to come up with a syntax for specifying responsive images
that satisfies multiple use-cases.
Their most popular attempt so far,
only hits 2 of the 3 major use-cases,
and has certain aspects that implementors seem to be rather unhappy with.
This document defines a new attempt at the problem, sketched out in collaboration between me and John Mellor, which solves all three of the major use-cases, while avoiding implementor concerns, and hopefully being very easily usable.
To make things somewhat clearer, I’ll outline here the three use-cases that the responsive images community has been attempting to address.
In addition, there’s a strong requirement that the solution be friendly to the browser’s preloader, which scans the document for urls to start downloading quickly, as the connection delay is a huge factor in the feeling of "slow" sites on mobile devices, and so starting the connection as early as possible is a big win in perceived performance. This limits what kind of information you can rely on, as the preloader only has access to a small amount of data from the page.
Add a set of attributes to
these are the src-N attributes
When loading an image,
these attributes are consulted first,
in numerical order.
If none of them are valid or match,
then the plain
src attribute is used to load the image.
Note: It’s possible to integrate
srcset into this if necessary,
but it would be nice to avoid doing that.
This completely replaces the
The grammar for the attributes is:
<src-n-attribute> = <media-query>? [ <x-based-urls> | <viewport-urls> ] <x-based-urls> = [ <url> <resolution>? ]# <viewport-urls> = <size-viewport-list> ; <size-based-urls> <size-viewport-list> = <image-size> [ ( <viewport-size> ) <image-size> ]* <image-size> = <length> | <percentage> <viewport-size> = <length> <size-based-urls> = [ <url> <integer> ]#
The above grammar must be interpreted per the grammar definition in [CSS3VAL]. For the purposes of the above grammar, the <url> production is simply any sequence of non-whitespace characters that does not end in a comma or semicolon. All other terminal productions are defined as per CSS.
The terms and use of this grammar are explained further in the following sections.
Note: Any explanations of how the attributes and their values are processed that appear in this section are non-normative. The normative definition of the processing model is in the "Processing" section.
To solve the basic art-direction use-case, the src-N attributes allow a media query to be provided at the beginning of their value.
I want just the second clause of the
media_query grammar in Media Queries 4,
where you have "(foo:bar) and (baz:qux)" and that’s it.
I should go fix the grammar section there to expose this more cleanly.
Each valid src-N attribute is checked in numerical order,
and the first one to have a matching media query
(or no media query at all)
is chosen as the source of candidate urls for this
These could be referenced like:
<img src-1="(max-width: 400px) pic-small.jpg" src-2="(max-width: 1000px) pic-medium.jpg" src="pic-large.jpg" alt="Obama talking to a soldier in hospital scrubs.">
Note: Putting the final url into a
src attribute like that isn’t required;
in fact, if using any of the more advanced pieces of this feature,
like multiple resolutions,
it would have to be in a src-N attribute
src-3 would be most appropriate here).
Still, having a final fallback in
src is a good idea,
as it means that down-level browsers will still be able to correctly download the image.
Note: This feature is intended to be used with distinct images. Look at the "Viewport" subsection about choosing among multiple copies of the same image based on viewport size.
To solve the resolution use-case, the src-N attributes allow multiple urls to be provided, each with an indicator of their resolution (the ratio of image pixels to CSS pixels).
Instead of a single url, simply provide a comma-separated list of urls/resolution pairs, where each pair is a url, followed by whitespace, followed by a CSS <resolution> value. A url provided without a <resolution> is assumed to be at 1x resolution.
Assume that I’ve already edited Images 4 appropriately so that x is a valid resolution unit, equivalent to dppx.
<img src-1="pic.png, picHigh.png 2x, picLow.png .5x">
The choice of which image to load is left to the user agent, based on its knowledge of the screen’s pixel density, the device’s bandwidth, and whatever other factors it deems relevant to the decision.
The intrinsic size of the chosen image is equal to the actual number of image pixels in each dimension, divided by the chosen resolution multiplier, in CSS px units. For example, if "pic1.png 2x" is chosen, and is 100 pixels wide, its intrinsic size is 50px.
The previous section on resolution discrimination had a hidden assumption which may not always be true: that the image being presented is meant to be a single, static size. That is, regardless of the size of the screen, the image will always be, say, 400px wide.
This assumption is not always true. There are two major reasons why this may be so:
Either of these issues can be addressed with Media Queries, but it gets complicated when resolution discrimination is mixed in - if you’re displaying the same image at a variety of sizes, a particular image file may be appropriate as a 1x image on large screens, but would also serve perfectly well as a 2x image on smaller screens. Dealing with this requires you to repeat urls multiple times, and can require some non-trivial math. (See the next example for a simple demonstration of the code bloat.) Further, the code so produced is not actually forward-compatible, either - it’ll act badly when even higher-density screens arrive, unless you further bloat the syntax by pre-emptively writing out higher-density versions.
To avoid these issues, this specification defines a shortcut syntax to address the case of a variable-sized image.
For the first case,
of an image that is sized as a fraction of the viewport,
simply provide the target
<img> size as a percentage,
followed by a semicolon,
followed by a comma-separated list of image urls
and the widths of the images in image pixels.
Using this information, the browser can determine how wide the
<img> will end up being,
and convert the image widths into effective densities.
<img src-1="100%; url1 400, url2 800">, and the viewport’s width was 320px, this is equivalent to specifying
<img src-1="url1 1.25x, url2 2.5x">.
On the other hand, if the viewport’s width was 800px,
it would be equivalent to specifying
<img src-1="url1 .5x, url2 1x">.
Regardless of the viewport’s size, the browser will understand which url is appropriate to download without you having to do any of the math yourself.
<img src-1="100%; pic1.png 160, pic2.png 320, pic3.png 640, pic4.png 1280, pic5.png 2560">
With this one declaration,
a high-res phone 320px wide can correctly choose to download
pic3.png (an effective 2x resolution),
while a large desktop screen with 96dpi will correctly choose to download
pic4.png (approximately a 1x resolution).
Anything at higher, lower, or in-between sizes and resolutions will also be appropriately catered for,
without the author having to explicitly figure out reasonable breakpoints
and categorize each image appropriately for each.
Using just Media Queries, the markup would instead look something like:
<img src-1="(max-width: 400px) pic1.png .5x, pic2.png 1x, pic3.png 2x" src-2="(max-width: 800px) pic2.png .5x, pic3.png 1x, pic4.png 2x" src-3="(max-width: 1600px) pic3.png .5x, pic4.png 1x, pic5.png 2x" src-4="pic4.png .5x, pic5.png 1x">
This example is obviouslly substantially more verbose,
and also less powerful.
For example, when screens reach 3x or 4x density,
those devices will still be stuck downloading 2x resources,
even though a 3x or 4x version exists for most screen sizes,
unless the author comes back and updates every
<img> element in their page.
Further, the breakpoints chosen above were simply guessed at, and are likely not optimal. Doing the math to find the optimal breakpoints isn’t hard, but is definitely non-trivial.
For the second case, when the size of the image varies based on breakpoints in your layout, the syntax is slightly more complicated. The first and second parts are still separated by a semicolon, and the second part is still a list of urls and image sizes.
The syntax of the first part, though, is slightly expanded. Rather than being simply an image size, it’s an alternating list of image sizes and viewport breakpoints, with the breakpoints in parentheses to help separate them visually. The breakpoints must be in ascending order, as the image size is chosen by finding which two breakpoints the viewport’s size sits between, and selecting the image size between those two.
Assuming that the same image is supposed to be used at all of these layouts (that is, you aren’t doing art-direction cropping to optimize the display of the image for a given size), then all of these cases can be addressed by a handful of images at various sizes, and the following code:
<img src-1="100% (30em) 50% (50em) calc(33% - 100px); pic100.png 100, pic200.png 200, pic400.png 400, pic800.png 800, pic1600.png 1600, pic3200.png 3200">
The first part of this attribute sets up the layout breakpoints at 30em and 50em, and declares the image sizes between and around these breakpoints to be 100%, 50%, or calc(33% - 100px).
The six images automatically cover every reasonable possibility. For small screens (phone size, or even smaller, like watches), anything from the 100 pixel wide image to the 800 pixel wide image may be downloaded, depending on screen size and density. For medium and large screens, anything from the 400 pixel wide image and up may be chosen. The author doesn’t have to do any math or complex figuring, just provide the image in enough sizes to cover everything they believe reasonable.
Again, doing the same thing just with Media Queries is much more verbose.
Note: Notice that the full set of CSS <length> values are actually available for image sizes,
including things like calc().
Using this, you can get as close to the precise size that the
<img> element will be as you wish,
though just getting “close enough” as I did in these examples is more than sufficient in most cases.
Similarly, viewport sizes can be specified with the full set of <length> values,
which are interpreted in the same way that they would be in a Media Query like min-width.
For example, em units are interpreted relative to the user’s default font size, etc.
Note: Also, all of the examples given here size the various images as powers of 2, doubling in size as they get larger. This is merely for convenience, as it’s easy to downsample an image by powers of 2, but is not a limitation - feel free to provide images at any size you desire. This will become more important in time, as 3x screens come into use and you wish to give them a well-targeted image to download, rather than having to decide between the 2x and 4x versions.
The intrinsic width of the image is equal to the image size chosen from the provided list. If the image has an intrinsic ratio, the intrinsic height of the image is its intrinsic width multiplied by the ratio. Otherwise, it has no intrinsic height.
This section describes the processing model for images.
<img> element is encountered on the page,
run the following steps for it:
Is this the right place to say "fire a load error" or whatever?
Update the image data, choose the right candidate, etc, etc, hook up to the right terms in HTML. The actual choice is UA-specific.
This section describes how to obtain the image candidates
from an HTML
The input to this algorithm is an HTML
The output of this algorithm is a (possibly empty) list of image candidates,
where each candidate is a pair composed of a url and a resolution.
Return image candidates, and abort this algorithm.
For each pair of values in viewport data:
Abort this sub-algorithm.
Return image candidates.
To obtain a candidate from src from an element, follow these steps:
srcattribute, return a list consisting of a single image candidate, where that candidate’s url is the value of the
srcattribute and its resolution is 1x.
In the event that this proposal "wins",
but browsers have already shipped "basic"
(just support for resolution discrimination)
and uptake is high enough that they can’t take it back,
then we can easily integrate
srcset into this fallback behavior.
In other words,
srcset doesn’t hurt this proposal
(though it would be ideal if it didn’t exist alongside).
No properties defined.
media_querygrammar in Media Queries 4, where you have "(foo:bar) and (baz:qux)" and that’s it. I should go fix the grammar section there to expose this more cleanly. ↵
srcset(just support for resolution discrimination) and uptake is high enough that they can’t take it back, then we can easily integrate
srcsetinto this fallback behavior. In other words,
srcsetdoesn’t hurt this proposal (though it would be ideal if it didn’t exist alongside). ↵