Using SVG in CSS with JavaScript detection

Warning This article was written over six months ago, and may contain outdated information.

With the release of IE9 and Firefox 4 all major browsers are going to support using SVG in the img element or as a CSS background image, which is great news as SVG images are good for high definition, scalable websites. I’ve written a couple of posts recently about using SVG with the background-image property, and how to cope with browsers that don’t support it. The method I came up with works, but is far from elegant; for one thing, it doesn’t allow for transparency.

Another approach we can take to the problem is to use JavaScript to detect SVG support. Alexis Deveria wrote a script which detects if your browser supports SVG and, if not, replace the images with PNG. It’s a good script, but I wondered if there was an alternative.

I’ve come up with a script based on Alexis’s, but which simply adds a class to the body of the document, allowing you to specify alternative images if SVG support isn’t implemented on a visitor’s browser. Update: Changed the script to use onload instead of addEventListener to ensure compatibility with IE. Still looking into Opera issue.

Here’s the script:

function setCSS() {
  var docBody = document.getElementsByTagName('body');
  docBody[0].className = 'svg';
}
function SVGDetect() {
  var testImg = 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNzUiIGhlaWdodD0iMjc1Ij48L3N2Zz4%3D';
  var img = document.createElement('img');
  img.setAttribute('src', testImg);
  img.onload = setCSS;
}
window.onload = SVGDetect;

This creates an img element with an SVG data URI and tests to see if the browser loads it; if it does, it adds a class of svg to the body. To finish the method you just need to add alternatives in your stylesheet:

div { background-image: url('image.png'); }
.svg div { background-image: url('image.svg'); }

Here’s a demo: Using SVG in CSS with JavaScript detection. View it in Safari, Chrome, Opera, IE9 beta or Firefox 4 beta to see the SVGs, and Firefox 3.6 or IE8 to see the PNGs. Try zooming in to the page to see the advantage of using SVG.

There are a couple of drawbacks with this method that need to be ironed out: first is that in theory it doesn’t work in browsers which allow SVG in the img element but not in background-image — in practice, however, there are no browsers where this is an issue; second is that it loads the PNG images first, and there’s a brief delay before the SVG images replace them — the script definitely needs tweaking to stop this, so consider it Version 0.1.

This technique is for the CSS background-image only; if you want to replace img elements I advise you to use Alexis’ script instead. As always, if you see a way in which my code could be optimised, don’t hesitate to let me know.

Update 20/05/12: The script I came up with in this post was a first attempt which I thought at the time was probably easily improved upon. See the comments of this post for different approaches which may be better.

7 comments on
“Using SVG in CSS with JavaScript detection”

  1. Actually the test didn’t work for me in opera 10.62.

  2. Wouldn’t an SVG browser load both images anyway, and then just use the SVG image even though both were downloaded & cached?

  3. @Spadar — Thanks, I’ll look into that.

    @Devon — That’s certainly the way it works at the moment, both PNG & SVG images are loaded; I’m not sure if that would be the case if I could get the script to load when the DOM is ready. I’ll look into it as I develop the script.

  4. Actually, with the current firefox it is an issue: FF allows SVG in the img element but not as background-image. It probably will work in the next release (version 4.0) though, you can find a bug page here: (down in the comments) https://bugzilla.mozilla.org/show_bug.cgi?id=276431

  5. On the script above, you’re using…

    img.onload = SVGDetect;

    I believe you want…

    window.onload = SVGDetect;

    Like you do on your demo page.

  6. Wouldn’t you want to use PNG if SVG wasn’t supported?

    So why not do something like this:

    function SVGDetect(){
      if(!document.createElementNS && !document.createElementNS(‘http://www.w3.org/2000/svg’, ‘svg’).createSVGRect)
      document.getElementsByTagName(‘body’)[0].className += ’ nosvg’
    }
    window.onload = SVGDetect;
    
  7. Thanks. Worked for me to detect Firefox 3.5 which doesn’t support svg background images in css.