Responsive Images

Working Demo - use your dev tools and turn off caching and watch the different image assets load as the viewport is resized.

In the world of responsive design, the ultimate goal in handling images is to load different versions of an image based on need. Don't stretch small images on big displays. Don't load massive images on tiny displays, slowing web sites down and wasting data.

Reconciling Variables

The problem: Many variables can affect the appropriate size image to load. The information that the browser knows is complimentary, but mutually exclusive from the information that the server knows at the time it is needed.

Browser / User's Device Knows
Server / Designer Knows
Size of screen
Pixel density of display
Quality and speed of network connection
User preferences (e.g. accessibility settings)
Size of the image in pixels
Size the image will occupy in viewport

The solution: Tell the browser the information it doesn't already know and let it decide which image asset to use.

This does not mean telling the browser which image to use! It means giving the browser the information it doesn't already know, offering size options, and letting it make an informed decision about which one to download.

Tell the browser:

  • Image dimension in pixels
  • Final size the image will be displayed on the page

Having all the variables, the browser will then determine which image to load based on all conditions - display size, density, even network speed.

Simple svg formatted vector images are a great start, because they're already a scaling vector. No special code necessary.

There are two general use cases for responsive images - resolution switching, and art direction.

Resolution Switching

This is the most common use case, which is that you want to load different sizes of the same picture. Here's an example:

<img src="cat.jpg" alt="cat"
  srcset="cat-160.jpg 160w,
    cat-320.jpg 320w,
    cat-640.jpg 640w,
    cat-1280.jpg 1280w"
    sizes="(max-width: 480px) 100vw,
           (max-width: 900px) 33vw,
  • img tag is always needed
  • src is always needed and should provide a default/fallback image, particularly for old browsers that don't support srcset.
  • srcset + w (width) descriptors of the actual pixel width of the image.
  • sizes is required any time you're using srcset.
  • sizes is a list of conditions (similar to media queries) along with the size the image will be displayed in your layout. You can use any type of units here (%, em, px, viewport units, etc. You can even use the calc() function.
  • Always provide the sizes attribute with a default size (in this case 254px).

Art Direction

Art direction is when you want to load a different picture content based on certain conditions. For example, a horizontal image on large displays may become a cropped, portrait version of the image on mobile.

<picture> is designed for art direction as opposed to simple resolution switching. It's also for image type switching, which is an excellent, forward looking feature.
    <source media="(min-width: 900px)"
    <source media="(min-width: 650px)"
    <img src="cat.jpg" alt="cat">
  • Each <source> can have a full set of srcsets and sizes just like those used for resolution switching.
  • An img tag is still always required.
  • This can also be used to offer multiple formats of the same picture, so browsers that support newer image formats like webp can take advantage of better image compression.

New Picture Formats

These new image formats improve on the compression algorithms of traditional jpegs, improving file sizes without reducing quality. None of them are cross-browser supported yet though, so for now they should only be used with the <picture> tag defined as additional sources.

Supported Browsers
Chrome, Opera, Android browsers
IE and Edge
Safari (both flavors)
APNG (Animated PNG)
.png or .apng

Moving Into CSS


Not well supported yet. Use media queries to swap out background images.

(Lack of) Separation of Content and Styles

Why can't this be done in CSS? What happened to separation of content and styling?!

When loading a web page, the browser aggressively opens multiple connections to download all the assets it finds in the HTML as soon as it sees them. This begins happening before the CSS is being parsed.

This feature in browsers is called "pre-loading" or "speculative asset downloading" depending on which browser vendor you talk to. Both Firefox (Gecko) and Chrome (Blink) conducted performance tests, and both found that web pages load 20% faster using this feature alone. So that's not going to change any time soon.

This creates a problem for developers - we can't tell the browser information about images using CSS, because that's after the browser has already opened connections and started downloading images!

Fixing this, for now, requires putting these style related settings in the HTML markup. It's not a perfect solution, but it works.

How to Set Image Breakpoints (How many images do we offer?)

No real clear answer, but Jason Grigsby does a good job addressing the approach.

Using some math to calculate how many "wasted bytes" are loaded for images at different sizes, there is more waste as the image gets larger.

Loading anything larger than the way it will be displayed is technically wasting bytes. So in theory, you shouldn't space the image breakpoints evenly, you should provide more sources toward the larger end of the spectrum.

Images with a lot of texture and color that make jpeg compression less efficient, benefit the most from having additional options. Images that compress well anyway technically don't need as many sources. This however is getting pretty far into the weeds looking at each image asset individually. Very tedious.

You can also optimize the source options based on which size image is downloaded most often.

The bottom line here is again that there's no silver bullet answer, and that really this process should be automated or done by a computer. In the future, it probably will be.