Retina screen ready: Using vector SVG images and still supporting crappy browsers
on
I’m not going to dive into why you should use SVG images in your web pages since that’s been well covered elsewhere. Once you’re convinced that SVG images are the way to go, here are a couple of quick little scripts for safely using SVG images in your sites: https://github.com/jonathandean/svg_fallback. The recipe is pretty simple:
- Create both an SVG and fallback version for non-compatible browsers (such as a PNG or JPG.) Check out retinafy.me for a comprehensive guide.
- Use a standard image tag with the src attribute pointing to your .svg image
- Reference your fallback image one of two ways:
- Put a .png file with the same name in the same directory. It will simply become the following in a non-SVG browser:
- Add a data-svg-fallback attribute to the image tag pointing to the fallback version. Use this method if your fallback is not a PNG or if it lives in a different directory
<img src="images/logo.png" alt="" />
<img src="images/logo.svg" alt="" data-svg-fallback="images/fallback/logo.jpg" />
which becomes:
<img src="images/logo.jpg" alt="" />
- Load the svg_fallback.js or svg_fallback.jquery.js script before the end of your closing body tag, depending on your preference and whether or not you use jQuery. The jQuery version can also be safely used in your head tag if you wish since it uses a DOM-ready handler, but you should always avoid loading JavaScript in the header when possible.
<img src="images/logo.svg" alt="" />
That’s it! For most browsers, the SVG version will be used as is. For browsers that can’t use the SVG image, the script will replace all images on the page that have a .svg file extension with the fallback version.
CSS image replacement and background images
The script will add either an svg or no-svg class to the body element, which you can use in your CSS rules to specify which version to use. Here’s an example:
h1.logo {
background: url(logo.svg);
}
body.no-svg h1.logo {
background: url(logo.png);
}
This example will use logo.svg as the background image for h1.logo when SVG is available and logo.png when not. (Other styles removed to simplify the example.)
The other thing to keep in mind is that on retina screens you also likely want to set the scale of the background image. Using Thomas Fuchs‘s retina screen media query, it may look something like this for a 100×100 pixel image:
h1.logo {
background-image: url(logo.svg);
background-size: 100px 100px, 100% 100%;
}
body.no-svg h1.logo {
background-image: url(logo.png);
}
@media (min--moz-device-pixel-ratio: 1.5),
(-o-min-device-pixel-ratio: 3/2),
(-webkit-min-device-pixel-ratio: 1.5),
(min-device-pixel-ratio: 1.5),
(min-resolution: 144dpi),
(min-resolution: 1.5dppx) {
h1.logo {
background-size: 50px 50px, auto;
}
}
For more on this, I strongly recommend you pick up a copy of retinafy.me.
Using with Ruby on Rails and the asset pipeline
If you are using Rails and the asset pipeline you should put your images in the page doing something like this:
"#{image_path('logo.png')}", :alt => "Use an alt value for images!"} %>
Just using the default behavior of automatically using a .png extension for the same file path won’t work when the asset pipeline adds the digest to the filename during asset compilation.
Credits
Credit for the basic idea of the script goes to Thomas Fuchs and this example for his retinafy.me book: https://gist.github.com/3202087. There are just a couple of key differences between his version and my adaptation. The original script requires that JavaScript sets the image src regardless of which image is being used. I prefer to take the philosophy of SVG-capable-browsers-first a little farther in that the default SVG image is shown immediately when rendered in the page without waiting for the script to run. His version also assumes that the fallback image is always a .png file in the same directory as the original, which doesn’t work if you prefer .jpg images as the alternative or if you are using the Rails asset pipeline with the hash digests turned on (as explained above), which the default and recommended way for production applications.
New blog post: Retina screen ready: Using vector SVG images and still supporting crappy browsers: http://t.co/P748pk0x