Good or bad idea: Replacing all images on a mobile website with CSS property "content:url()" for retina displays

StackOverflow https://stackoverflow.com/questions/21433643

Question

We're currently building a website for mobile devices. Supported operating systems and browsers should be:

  • Android 4.x (Stock Browser, Google Chrome)
  • iOS6+ (Safari, Google Chrome)

In order to also support high resolution displays we evaluated various techniques and libraries to automatically replace images with their high-res pendants:

Attempt 1: retina.js http://retinajs.com/

The first attempt was to use a normal <img> Tag like this: <img src="foo.png"> and use retina.js to let it automatically replace the src Attribute with the name of the retina image (foo@2x.png). This works but has 2 downsides: First, it will create unwanted overhead because both, the original as well as the retina image, would be loaded and second, if there is no retina image available it will cause lots of 404 errors on server log which we do not want.

Attempt 2: picturefill.js https://github.com/scottjehl/picturefill

This framework uses some weird html markup based on <span> elements. For me it looks like as if the author tried to mimic the proposed <picture> element which is not a standard (yet), see http://picture.responsiveimages.org - I don't like this approach because of the weird markup. For me it doesn't make sense to semantically describe images with spans.

Attempt 3: Replace images via CSS property background-image

I see sometimes people using CSS media queries to detect retina displays and then set a background-image on a div (or similar element) with a higher or lower solution picture. I personally don't like this approach either because it completely discourages creating semantically good markup à la <img src="foo.png">. I can't imagine building a website just with div's and then set all images as background images - This just feels very weird.

Attempt 4: Set images via CSS property content:url(...)

As proposed here Is it possible to set the equivalent of a src attribute of an img tag in CSS? it seems to be possible to overwrite the src Attribute in img Tags via CSS using the property content:url(). Now, here is the plan: We set img tags for each image with a transparent blank 1x1 png referenced in its src attribute, like this: <img id="img56456" src="transp_1x1.png" alt="img description">. Now this is semantically ok and also valid against the W3C validator. Then we load a CSS Stylesheet that sets all the images on the website via Media Queries.

Example:

#img56456{content:url(foo.png)}
@media (-webkit-min-device-pixel-ratio: 2){ 
    #img56456{content:url(foo@2x.png)}
}

Now, this approach works pretty good:

  • No overhead
  • Solid markup
  • Works on the required devices/browsers
  • SEO for Images is not requirement here

Now, could this approach cause any side effects we didn't think of? I am just asking because I know it works but kinda "feels" weird to set all images via CSS and I also found this comment on this approach on SO Is it possible to set the equivalent of a src attribute of an img tag in CSS?:

"Worth to add that even in browsers that support assigning content to img, it changes its behavior. The image starts to ignore size attributes, and in Chrome/Safari it loses the context menu options like 'Save image'. This is because assigning a content effectively converts img from empty replaced element to something like <span><img></span>"

Could this be a problem? (I didn't notice any sizing problems and the context menu is not a requirement)

Was it helpful?

Solution 2

The new version of picturefill http://scottjehl.github.io/picturefill/ doesn't rely on <span> any more. Instead it simply uses the official HTML5 srcset attribute and mimics its behavior if the browser doesn't support it, so for me this is the ideal solution after quite a while now.

Using the CSS property content:url(...) was a neat little idea but it made things a little complicated and hackish too.

So, to answer my own question: No, it's a bad idea. Using the new version of picturefill is a way better solution. You can even remove it after a while when newer versions of all major browsers support the srcset attribute and you'll still be standard compliant. http://caniuse.com/#search=srcset

Example:

<img srcset="examples/images/small.jpg, examples/images/medium.jpg 2x" alt="A giant stone face at The Bayon temple in Angkor Thom, Cambodia">
<script src="picturefill.js"></script>

OTHER TIPS

There are lots of advantages and disadvantages, but one disadvantage is that the image won't be cached. This is more of a problem on mobile devices where internet is generally slower and more expensive for the user (if on a data connection not wifi).

I don't know about those libraries but you could use media-queries, depending on how many images you have, otherwise it would be lots of code variations to write. And have a threshold screen size at which point you use a different file. Only one file is actually loaded, even though you specify both in the media-queries.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top