SVG fallbacks: which method should I use?

We already know that SVGs are great. They scale to (almost) any size without losing clarity, they look great on retina displays, and they compress very well. One thing we have to remember when we get excited about adding SVGs to our sites is that there are still people out there who can't see them. According to caniuse, people using older versions of IE and Android are likely to be missing out.

In many cases, like e-commerce sites, it's really important to make sure that as many customers as possible can see meaningful images. When I first started testing websites, I always had to go back and address the SVGs that weren't supported on certain devices and browsers. These days, when I start a project it's one of the first things I think about. I know I need to include fallbacks for SVGs, but today my question is: Which fallback method is best? There are so many out there to choose from.

What kind of fallback are we talking about?

I have a bunch of SVGs to include in my current site project and I'm considering the best way to display them. I have grouped them into two categories:

  • Decorative icons, which are clearly explained by a label
  • Icons that convey information

Icons that are explained by surrounding text are not vital content. For example, an icon inside a button, alongside the word 'add to basket' is not really needed. Therefore, they are added as background images in CSS. It doesn't really matter if they don't show up, but if you want to provide a fallback it's pretty simple. Place the .png fallback before the .svg image, so if SVG is supported in the browser, the .svg image will overwrite the .png.

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

Icons that convey information should be in the foreground as HTML elements. In this case, some of these icons are inside links. You definitely shouldn't have any empty links, so this is a clear indication that they should be in the HTML. In this post I'm going to consider some SVG fallback methods for HTML.

Fallback for SVG using <object>

The <object> method appears to have been around for a while and it seems really simple. The SVG is added to the data attribute. If the object element is not supported, the contents inside will be used instead. I like this because the fallback doesn't have to be an image; it can be any type of HTML content, including text.

<object type="image/svg+xml" data="image.svg">
  <p class="text-fallback">
    Some text as an alternative to the SVG image.
  </p> 
</object>

<image> fallback for inline <svg>

An <image> element placed inside an <svg> works slightly differently to an <image> that stands alone in HMTL.

Jake Archibald explains that in the old days of the web, some people used to accidentally type <image> instead of <img>. As a result, browsers decided to automatically correct this to <img>, and so it's been doing it ever since.

The SVG <image> does not do this because it is used to embed other files within the SVG element. One of the main differences between the two is that in an <svg> element, you need to specify the URL of the image file within the xlink:href attribute. In HTML, you specify the URL in the src attribute.

<svg viewBox="0 0 136 61">
  <!-- SVG code goes here -->
  <image src="image-fallback.png" xlink:href="null"> 
</svg>

Newer browsers read the <svg> code, whereas older browsers that don't support it will use the fallback image. Strangely, IE downloads the fallback, even if it doesn't use it.

I think this method is more suitable for smaller images like icons—otherwise the SVG code could get very long.

I've also found a variation of this. This time the image element contains both xlink:href and src attributes. A height and width is required to make the image fill the entire size of the SVG. Both the image and svg can be styled in the CSS, but it can get a little complicated when trying to get the images to size correctly on responsive layouts.

<svg width="100" height="100">
  <image xlink:href="image.svg" src="image.png" width="100" height="100" alt="" /> 
</svg>

This feels like a little bit of a hack, but it has some advantages. No JavaScript or dependencies are required and it's very simple to implement. The main disadvantage that sticks out to me is the issue with sizing images for a responsive layout.

Inline source swapping in <img>

In this example, we can use inline JavaScript to swap the .svg image for a .png one when the browser doesn't support SVG.

<img src="image.svg" onerror="this.src='fallback-image.png'; this.onerror=null;" alt="">

A slight disadvantage of this method is that browsers which use the fallback will download both images. However, in this case, I think it's a performance penalty that won't be much of a problem because the icons are pretty small in size.

More options

I read a brilliant article by Amelia Bellamy-Royds, which explains SVG fallbacks in great detail. This post is an overview of the three most appealing fallback methods I've seen, based on their browser support, ease of implementation and maintenance.

Tags: