Responsive images using CSS3

Future CSS implementations should allow for some form of responsive images via CSS alone. This is an early idea for how that might be done. However, a significant drawback is that it would not prevent both “mobile optimised” and larger size images from being requested at larger screen resolutions.

Note that the CSS presented here is not supported in any browsers at the time of writing.

This method relies on the use of @media queries, CSS3 generated content, and the CSS3 extension to the attr() function.

The principles are basically the same as those underpinning Filament Group’s work on Responsive Images. The source image is “mobile optimised” and the urls of larger size images are included using HTML data-* attributes.

<img src="image.jpg"
     data-src-600px="image-600px.jpg"
     data-src-800px="image-800px.jpg"
     alt="">

Using CSS @media queries you can target devices above certain widths. Within each media query block, images with larger alternatives can be targeted using an attribute selector.

CSS3 generated content allows you to replace the content of any element using the content property. At the moment, only Opera 10+ supports it. In CSS 2.1, the content property is limited to use with the :before and :after pseudo-elements.

By combining the content property with the CSS3 extension to attr(), you will be able to specify that an attribute’s value is interpreted as the URL part of a url() expression. In this case, it means you will be able to replace an image’s content with the image found at the destination URL stored in a custom HTML data-* attribute.

@media (min-device-width:600px) {
    img[data-src-600px] {
        content: attr(data-src-600px, url);
    }
}

@media (min-device-width:800px) {
    img[data-src-800px] {
        content: attr(data-src-800px, url);
    }
}

Fork the Gist

Issues

Unfortunately, there are a number of issues with this technique.

  1. It doesn’t prevent multiple assets being downloaded at larger screen widths because network activity kicks in before CSS is applied. That means, for example, that desktop environments would make 2 HTTP requests for an image and have to load more assets than if they had been served only the larger image in the source.
  2. It makes the assumption that wider screens are tied to better internet connections.
  3. It forces authors to create and maintain multiple image sizes for each image.
  4. At present, using the context menu (or drag and drop) to copy the image will result in the source file being copied and not the replacement image.
  5. It doesn’t account for devices with different pixel densities.

6 comments

#

BrianMB says…

I applaud this clever solution, but it is one for a problem that will quickly disappear beginning this year with the widespread distribution of 4G radios and HD screens on handheld devices.

In the years to follow, there will be even smaller (not greater) movement to deliver the same content (if not layout) to handheld and non-handheld devices.

#

Daquan Wright says…

Nice article. I’m not new to working with websites, but I’m pushing my knowledge as far as I can.

Getting the same layout on all devices is impractical, so that isn’t my goal. Just as long as I can deliver the functionality and content on various platforms.

Maybe I can implement these techniques some day.

#

Adam Mark says…

Interesting idea … but a slippery slope to stuff more content directives into CSS. Consider audio, video and other data that can be optimized for mobile or reformatted in some way for non-desktop devices (e.g. TV). Also, how would you handle dynamic images, i.e. images that are not baked into the site design?

@BrianMB I agree at some point we’ll have the bandwidth to deliver the same content to any device, but it’s probably far off.

#

Oncle Tom says…

Do you think there would be a way to use a JavaScript fallback to avoid the double loading of pictures?

#

Brett Jankord says…

I know this post is a little old but wanted to share my solution to your 5th issue, devices with different pixel densities. https://gist.github.com/2572816

I do think you are on to something that deserves some more research. I like the concept of using solely CSS to handle image src modifications, this makes it a lot easier to maintain/update. I believe a solution that pairs image-sets() and URI templates would work the best but is just hypothetical now. Here’s an example of what I’m talking about: https://gist.github.com/2572749

Comment on this post

Please wrap code fragments in <code> tags, wrap blocks of code in <pre><code>, and use JsFiddle to post working examples.