Falling back from SVG

, Alexander Goedde

With legacy browsers lacking SVG support still around, a bitmap fallback solution may still be needed. A simple JavaScript based method is presented.

Part 3 of a series

This is the third part in a series of blog posts on SVG:

  1. SVG - Super Vector Graphics
  2. Preprocessing SVGs for the Web in 3 automated steps
  3. Falling back from SVG

SVG - 14 years in the making

Initially specified in 1999, SVG predates Chrome, Firefox and HTML5. This long history means that, by now, basic support for the format can be found in all modern browsers.

Of course, the term "modern browsers" excludes IE8 and below and the Android browser up to 2.3.6 (and a few more obscure browsers).

three icons for file not supported or found
This is shown when a browser cannot render SVG like IE8 and below

IE8 and Android browser up to 2.3.6: that's still quite a number of users we're talking about. And while XP may be ending its lifespan, new cheap devices with old Android are still being released at the time of this writing.

Additionally, depending on what you do with SVG, and which specific features of the standard you use, support in other browsers can be lacking or buggy.

Both the complete lack of support, and implementations problems are going to diminish as a concern on the general web, but they won't go away anytime soon. There will be cases where SVGs to transport meaning result in the loss of information for a while yet.

All of this means one thing: you should still think about a solution which allows people with legacy browsers access to your website.

PNG - Fallback, not default

When working on a website, there is a temptation, as with all software development, to aim for a perfect solution. One which has every possible potential visitor covered, and disadvantages nobody.

A look at the logs for our company website, as well as those of the Open-source Web sites we are hosting1 shows that we don't have much of a legacy problem. Chrome and Firefox reign supreme, and problematic browsers such as older IE or Android are in between 1% and 2% .

Browsershare: Chrome, Firefox, and very little else
Not your usual Statcounter distribution

For us, a solution which keeps page loads times fast for 99% of visitors had to be SVG first. Support for bitmap images was to be a fallback only.

We also wanted as little extra work as possible for supporting the fallback - and for this to cover as many legacy browsers as possible.

This excluded clever things like canvg or Fabric.js which render SVGs on the canvas: IE8 doesn't have canvas support either.

The solution ideally also wouldn't affect the markup. For example, we didn't want do something like

   <object data='logo.svg' >
       <img src='logo.png' />
   </object>

Since we are, at the moment, only using SVG in the img tag, the obvious solution seemed to switch these to PNGs on browsers where no SVG support was detected.

The PNGs themselves were not an issue - we have a build process that creates optimized versions of our SVGs from out Inkscape design files. Adding a SVG-to-PNG conversion here wasn't hard - and, as importantly, a one-time only effort. We get PNG versions of the SVGs, which file names only differing by file extension at no extra cost. (See Preprocessing SVG for the Web for more details on the build process.)

Loop & rewrite

The solution needed to

  1. detect the lack of SVG support
  2. loop over all the images in the page
  3. rewrite any references to SVG images to PNG

This only loads the PNGs in the minority of cases where there is no SVG support (= no punishment for modern browsers) and doesn't add anything extra to the workflow of page coding.

Feature detection = Modernizr

Modernizr is just the quickest way to get feature detection. You can keep the download size down by creating a custom version which only contains the test you need. Of course, you could always dig into the code and just use the snippets that Modernizr itself does to detect SVG feature support. Here, we went with a custom version.

A simple loop & rewrite

The code that gets triggered if there's no SVG support is simple enough:


function switchToPNG () {
   // requires that SVG & PNGs exist at the same path
   // with only different file extensions

   var imgLinks = document.getElementsByTagName("img"),
      imgLinksLength = imgLinks.length;

   for(var i = 0; i < imgLinksLength; i++ ) {
      var cur = imgLinks[i],
         curLink = cur.src,
         curLinkType = curLink.split(".").pop(),
         curLinkBase = curLink.slice(0, curLink.lastIndexOf(".")),
         newLink;

      if(curLinkType === "svg") {
         newLink = curLinkBase + ".png";
         cur.src = newLink;
      }

   }
}

All we need to with this is to include the script somewhere at the root of templating solution.

This can most likely be optimized, but it works fine on IE8 and the old Android browsers. The extra load times for the images once it runs mean that any improvement here won't substantially speed up interaction for the user.

Drawbacks

For some the fact that our fallback relies on JavaScript may be problematic. The way we see it, the number of visitor browsers which both do not support SVG and have JavaScript turned off is likely to be so small that we didn't need to consider this.

The additional JavaScript to download is quite minimal. Zipped the extra download weight is about 7KB. When concantenating scripts, this seemed negligible.

The only real problem with our fallback is its limited scope. It doesn't do anything for SVG images used as part of CSS. This only occured once on our site, so was no deal-breaker at this time. Otherwise, there would need to be more code to go over all the style sheets and modify these as well. Doable, but not worth the time right now.

There, but for one thing

Our fallback relies on feature detection. While newer Android browsers do support SVG, their particular implemenation proved problematic.

The first problem was the expectation of an explicit height on the img tag containing the SVG, or on a container it filled completely.

Additionally, there were weird scaling issues on some images which did have explicit height set.

squashed icon
No, this really isn't 80px x 80px

The proper course would have been to do more testing to get to the root of the evil.

Time constraints meant that I went with something easy, but dirty: Sniffing the browser using a Yahoo script I'd used on a previous project1 and then switching to PNG when an Android browser is detected.

Yes, I know this isn't what you should do, but in the end there are only so many hours in the day, and there are more important things to do than develop nicer images to <0.5% of visitors.

The code for this? Well, here goes:

   // Android browser does very badly with SVG, so switch to PNG for this
   if(YAHOO.env.ua.android != 0 && YAHOO.env.ua.chrome === 0) {
               switchToPNG();
   }
   

How is your browser doing?

Since we're using this fallback solution on this page as well, here's a chance to see what the outcome is for your browser.

If the image below is blurry or pixelated, we've switched you to PNG.

Crossbar.io connectivity to front-ends and backends

Since nothing on the Web is ever perfect or finished: If you know your browser should display an SVG, then please let us know in the comments so that we can fix it!

Footnotes:

1. A WebGL demo allowing 3D-models to be turned in sync across browsers. IE11 claims WebGL support when using feature detection, but, at the time we put this online, couldn't run only some of the demos. Browser sniffing was the easiest way to give valid error feedback to the user.

Start experimenting and prototyping for IoT applications with Crossbar.io and Raspberry Pi!

Loaded with all the software you need to make the board part of WAMP applications!



Learn more

Recent posts

Atom Feed

Search this Site

Stay Informed

Sign up for our newsletter to stay informed of new product releases and features:
Community Chat