Built-in Browser Support for Responsive Images

HTML5 Rocks

Introducing the <picture> element

The <picture> element offers a declarative approach towards image resource loading. Web developers will no longer need CSS or JavaScript hacks to handle images in responsive designs. And users benefit from natively-optimized image resource loading—especially important for users on slower mobile internet connections.

Alongside the newer srcset and sizes attributes recently added to <img>, the <picture> element gives web developers more flexibility in specifying image resources. Write clear HTML markup and let the browser do the work of detecting any of the following scenarios, alone or in combination, to support responsive designs and improve web page load times:

Art direction-based selection
Is this a mobile device held in a portrait orientation or a wide desktop monitor? Load an image that is optimized for the given screen dimensions.
Device-pixel-ratio-based selection
Does the device have a high DPI display? Load a higher resolution image.
Viewport-based selection
Is the image meant to always fill a fixed proportion of the viewport? Load images relative to the viewport.
Image format-based selection
Can the browser support additional image file types that offer performance boosts such as smaller file sizes? Load an alternative image file such as WebP.

Use for art direction

The most common use of the <picture> element will be for "art direction" in responsive designs. Instead of having one image that is scaled up or down based on the viewport width, multiple images can be designed to more appropriately fill the browser viewport.

one image that is scaled up or down based on the viewport width
The result of using only one image that is scaled up or down based on the viewport width.
several different images to more appropriately fill the browser viewport
Use several different images to more appropriately fill the browser viewport.

Improve resource loading performance

When using <picture>, or <img> with the srcset and sizes attribute, the browser will only download the image explicitly stated for the matching scenario. This native implementation is compatible with HTML parsers and can take advantage of the browser's image caching and preloading abilities.

View a live demo

It's a fact that the Internet was created to host cat images. Using <picture> we can emulate the amazing ability of cats to adjust to the space given to them no matter how small or large.

an illustration of a cat stretching
Cat illustrations by @itsJonQ

Open the demo in a new tab with Chrome 38 or higher. Resize the viewport to see the cat in action.

As a starting point, this demo only shows off the bare minimum of features that <picture> has to offer. Let's dig into the syntax now.

The <picture> syntax

The following HTML and CSS snippet is everything that was used to implement the demo:

<style>
  img {display: block; margin: 0 auto;}
</style>

<picture>
  <source 
    media="(min-width: 650px)"
    srcset="images/kitten-stretching.png">
  <source 
    media="(min-width: 465px)"
    srcset="images/kitten-sitting.png">
  <img 
    src="images/kitten-curled.png" 
    alt="a cute kitten">
</picture>

Note how there is no JavaScript involved and no-third party libraries. The CSS <style> block is used only to style the image element and does not contain media queries. The native implementation of the <picture> element means that you can declare your responsive images using only HTML.

Use with <source> elements

The <picture> element has no unique attributes of its own. The magic happens when <picture> is used as a container for <source>.

The <source> element, which is used for loading media such as video and audio, has been updated for image loading and these new attributes have been added:

srcset (required)

Accepts a single image file path (e.g. srcset="kitten.png").

Or a comma-delimited list of image file paths with pixel density descriptors (e.g. srcset="kitten.png, kitten@2X.png 2x") where a 1x descriptor is assumed when it is left off.

Refer to Combine with pixel density descriptors for this in use.

media (optional)

Accepts any valid media query that you would normally find in a CSS @media selector (e.g. media="(max-width: 30em)").

Refer to the previous <picture> syntax example for this in use.

sizes (optional)

Accepts a single width descriptor (e.g. sizes="100vw") or a single media query with width descriptor (e.g. sizes="(max-width: 30em) 100vw").

Or a comma-delimited list of media queries with a width descriptor (e.g. sizes="(max-width: 30em) 100vw, (max-width: 50em) 50vw, calc(33vw - 100px)") in which the last item in the list is used as the default.

Refer to Combine with width descriptors for this in use.

type (optional)

Accepts a supported MIME type (e.g. type="image/webp" or type="image/vnd.ms-photo").

Refer to Load alternative image file formats for this in use.

The browser will use the hints passed in as attribute values to load the most appropriate image resource. The listing order of tags matter! The browser will use the first <source> element with a matching hint and ignore any following <source> tags.

Add a final <img> element

The <img> element has also been updated to be used within <picture> as the fallback in case a browser does not support the picture element or if no source element tags are matched. Using <img> within <picture> is a requirement—if you forget it, no images will show up.

Use <img> to declare the default image to be used within a <picture> block. Place <img> as the last child of <picture> since the browser will ignore any <source> declarations that occur after an <img> tag is found. The image tag is also where you should attach alternative text using the image element's alt attribute.

Combine with pixel density descriptors

Add support for high resolution displays using pixel density descriptors such as 1x, 1.5x, 2x, and 3x. The new srcset attribute applies to both <img> and <source> elements.

The example below supports 1x, 1.5x, and 2x resolution screens:

<picture>
  <source 
    media="(min-width: 650px)" 
    srcset="images/kitten-stretching.png,
            images/kitten-stretching@1.5x.png 1.5x,  
            images/kitten-stretching@2x.png 2x">
  <source 
    media="(min-width: 465px)" 
    srcset="images/kitten-sitting.png,
            images/kitten-sitting@1.5x.png 1.5x
            images/kitten-sitting@2x.png 2x">
  <img 
    src="images/kitten-curled.png" 
    srcset="images/kitten-curled@1.5x.png 1.5x,
            images/kitten-curled@2x.png 2x"
    alt="a cute kitten">
</picture>

Combine with width descriptors

Web Fundamentals covers the the new sizes attribute for the <img> element indepth:

"When the final size of the image isn't known, it can be difficult to specify a density descriptor for the image sources. This is especially true for images that span a proportional width of the browser and are fluid, depending on the size of the browser.

Instead of supplying fixed image sizes and densities, the size of each supplied image can be specified by adding a width descriptor along with the size of the image element, allowing the browser to automatically calculate the effective pixel density and choose the best image to download."

Here's an example of using the sizes attribute to set the proportion of an image to always fill 80% of the viewport. It is combined with the srcset attribute to supply four versions of the same lighthouse photo in widths of 160px, 320px, 640px, and 1280px wide:

<img src="lighthouse-160.jpg" alt="lighthouse"
     sizes="80vw"
     srcset="lighthouse-160.jpg 160w, 
             lighthouse-320.jpg 320w,        
             lighthouse-640.jpg 640w,
             lighthouse-1280.jpg 1280w">

The browser will use these hints to choose the most appropriate image resource to serve up based on the viewport width and hardware display resolution:

a photo of a lighthouse always filling 80% of the browser viewport
For example, the viewport on the left is approx. 800px wide. The browser will load lighthouse-640.jpg unless the device pixel ratio is 2x—in which case, lighthouse-1280.jpg will be loaded instead.

With the addition of <picture>, the sizes attribute can be applied to both <img> and <source> elements:

<picture>
  <source media="(min-width: 800px)"
          sizes="80vw"
          srcset="lighthouse-landscape-640.jpg 6400w,
                  lighthouse-landscape-1280.jpg 1280w,
                  lighthouse-landscape-2560.jpg 2560w">
  <img src="lighthouse-160.jpg" alt="lighthouse"
       sizes="80vw"
       srcset="lighthouse-160.jpg 160w,
               lighthouse-320.jpg 320w,
               lighthouse-640.jpg 640w,
               lighthouse-1280.jpg 1280w">
</picture>

Building on the previous example, when the viewport is at 800px and above, the browser will serve up a landscape version of the lighthouse version instead:

a photo of a lighthouse always filling 80% of the browser viewport except the larger viewport shows the landscape version of the lighthouse photo
The viewport on the left is above 800px wide so a landscape version of the lighthouse photo will be displayed.

Load alternative image file formats

The type attribute of <source> can be used to load alternative image file formats that might not be supported in all browsers. For example, you can serve an image in WebP format to browsers that support it, while falling back to a JPEG on other browsers:

<picture>
  <source type="image/webp" srcset="images/butterfly.webp">
  <img src="images/butterfly.jpg" alt="a butterfly">
</picture>

Additional code examples

Refer to Responsive Images: Use Cases and Documented Code Snippets to Get You Started on the Dev.Opera blog for an exhaustive list of examples combining <picture> and <img> with the srcset, media, sizes, and type attributes.

Try it out today

The <picture> element is currently available Chrome 38. Try it out with screen emulation in the Chrome DevTools.

If you have feedback on this new feature, drop us a line on the Chrome bug tracker.

If you're ready to start implementing <picture> today but also want to add support for responsive images in additional browsers, refer to the <picture> element sample on Web Fundamentals for using <picture> with a polyfill.

Comments

0