Skip to content

Instantly share code, notes, and snippets.

@madrobby
Created July 29, 2012 22:01
Show Gist options
  • Save madrobby/3202087 to your computer and use it in GitHub Desktop.
Save madrobby/3202087 to your computer and use it in GitHub Desktop.
Fallback to PNG if SVG is not supported
<!-- example for the http://retinafy.me ebook -->
<style>
div.rss {
background: url(rss.svg);
width: 32px;
height: 32px;
}
body.no-svg div.rss {
background: url(rss.png);
}
</style>
SVG with PNG fallback:<br>
<img data-svg="rss">
<br><br>
Background SVG with PNG fallback:
<div class="rss">
<script>
// This is just an example, and you'll likely need to adapt it..
//
// 1) adds a "no-svg" CSS class to <body> if SVG is not supported,
// so you can special-case CSS background images
// 2) loads all IMG tags that have a "data-svg" attribute set with
// either .svg or .png added to the url given in that attribute
//
// If you create new IMG tags with data-svg on the page later, you'll need to
// call the window.updateSVGIMG method.
(function(global){
var svg = !!('createElementNS' in document &&
document.createElementNS('http://www.w3.org/2000/svg','svg').createSVGRect)
if (!svg) document.body.className += ' no-svg'
;(global.updateSVGIMG = function(){
var i, src, extension = svg ? '.svg' : '.png',
elements = document.getElementsByTagName('img')
for (i=0;i<elements.length;i++)
if (src = elements[i].getAttribute('data-svg')) {
elements[i].src = src + extension
elements[i].removeAttribute('data-svg')
}
})()
})(this)
</script>
@madrobby
Copy link
Author

Obviously, you'll need to generate a PNG from your SVG. You can do that by installing librsvg with brew install librsvg and then using (for this example) librsvg-convert rss.svg > rss.png.

@jpsirois
Copy link

Would you sugest to always fallback to a Retina .png?

@andydavies
Copy link

Why do remove the attribute, is it incase the code is run a second time?

@neilstuartcraig
Copy link

Just thinking, it might be worth considering simply using javascript to rewrite the image filename (extension). You're going to cause a reflow of the page either way so probably not a huge difference either way there but rewriting the image filename (extension) would save a load of CSS especially on image-heavy pages - i guess you could use the lib above in a simple to easily convert all your SVGs to PNGs. Just a thought anyway...

@neilstuartcraig
Copy link

Actually, thinking about it, my proposal would remove the need for the expensive classname-based CSS selectors too :-)

@maxw3st
Copy link

maxw3st commented Jul 31, 2012

Looks like a good solution. Like the idea of giving the each (svg and fallback) a class. makes it useful across the doc, not just for the instance in your demo.

@bookwyrm
Copy link

bookwyrm commented Aug 1, 2012

Any particular reason not to include support for a fallback if JS isn't available?

@JeremiePat
Copy link

Your solution with img and data-* is a bit awkward, it's better to simply do as follow :

<object data="rss.svg" type="image/svg+xml">
    <img src="rss.png" alt="">
</object>

No JS, work everywhere ;)

@damonbauer
Copy link

@JeremiePat -

Works really well! The only con about this technique is wrapping the image in an does not link the image. So things like logos, social media icons, etc. won't function.

@pauginer
Copy link

If you want to avoid Javascript, as an alternative you can use a CSS-only technique I described at http://pauginer.tumblr.com/post/36614680636/invisible-gradient-technique

@jcaron23
Copy link

Another technique, as described here: http://tavmjong.free.fr/SVG/BUTTON_TEST/button_test.html (second code snippet) is to use an error handler on the img. Apparently it even works with IE5.5!

Jacques.

@tomsarduy
Copy link

Why not to use Modernizr? maybe you will need it for check others element support. Another way to fallback to .png using jQuery:

if (!Modernizr.svg) { 
    $(".rss").css("background-image", "url(rss.png)"); 
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment