Embedding accessible and crossbrowser-compatible SVGs into your website

When we relaunched our website in February, we had a set of design goals we wanted to achieve. Optimizing for high-resolution displays was one of them. Using an SVG (Scalable Vector Graphic) image for the company logo was a foregone conclusion.

2013-05-13

In this Post

After all, vector-based logos are uniquely suited for the web's vector image format. However, after reviewing our list of requirements (see below) we realized that there would be a few problems in satisfying them:

  • the logo should also be a link
  • logo and link need to work in every browser
  • any fallback solution for older browsers that don't support svg should also work without JavaScript
  • the implementation needs to fulfill accessibility requirements
  • the fallback implementation should be as automated as possible

When researching embedding SVG images we found some great resources:

Although there were already some good approaches and ideas on how to embed SVG images in a website, none of them fulfilled all of our requirements. Let's have a closer look at these approaches.

<object> with <img> as fallback

HTML

<a href="#"> 
    <object type="image/svg+xml" data="image.svg"> 
        <img src="fallback.png" alt="description" /> 
    </object> 
</a>

For modern browsers SVG images can be embedded by using an object in HTML and setting the type to SVG. For older browsers a fallback solution can be implemented by using <img> tag within the object. This works because older browsers would ignore the object and display the image. JavaScript is not necessary for this approach.

But the following problem can occur when linking <object> and <svg> tags: The link would not be displayed on browsers that support embedded SVG files. However if a “display:block” is added to the link then the link would be displayed, yet hidden "behind" the SVG image. At this point the user can only click around the logo and not directly on the logo! (source:  http://www.noupe.com/tutorial/svg-clickable-71346.htmlTo link this graphic properly, insert a link into the source code of the SVG file. This solution might be complicated for automation because the source code of the SVG file will change every time the SVG image is modified. Replacing images manually is also inconvenient.

Since modern browsers download both images (the SVG file and the fallback-image, which is usually a PNG file), a loss of performance is inevitable.

SVGWeb

HTML

<a href="#"> <script type="image/svg+xml"> <svg ...>...</svg> </script> </a>

SVGWeb is an open source drop-in JavaScript library that provides SVG support to Internet Explorer 6, 7, and 8 by transparently using Flash. (https://code.google.com/p/svgweb/This solution is relatively easy to implement. Just copy and paste the source code of the SVG into the script-tags; a fallback-image is not necessary. If the SVG code is wrapped with a link, this approach should work perfectly. SVGWeb will do almost everything. Unfortunately this solution has some serious disadvantages.

SVGWeb enhances old browsers to display SVG images. However if JavaScript were disabled SVG images would not be displayed! Based on the nature of the image, this can have drastic consequences. For example a logo is an essential element and its display on the website cannot fall victim to JavaScript being disabled. However displaying decorative (e.g. background) images may be less important for the user experience. 

Another drawback: the actual rendering is done via Flash, so users without Flash won't see the logos either.

Accessibility is a further problem. If the website should be configured for accessibility, a title and a description must be inserted in the SVG file. (http://www.w3.org/TR/SVG-access/#Equivalent

In general the SVGWeb solution suffers from dependency on JavaScript and Flash. It also requires time-consuming and complicated automation and manual replacement of images.

SVGeezy

HTML

<img src="image.svg" alt="description" />

SVGeezy is, in essence, a fallback plugin. It allows SVG files to be used for all assets, giving complete resolution independence. It checks if the browser supports SVG files. If the browser doesn’t, SVGeezy changes the src attribute of the image to a PNG file instead (or whatever is passed in). To use SVGeezy the SVG file needs to be inserted into an <img> tag and a corresponding PNG file must be provided. This solution can be linked and is accessible, but also does not work without JavaScript.

Modernizr and <noscript>

HTML

<a href="#img_modernizr_js_remplacement_nojs"> 
    <noscript>
        <img class="logo" src="logo.png" alt="A sample SVG button." width="186" height="235" alt="Logo Geeks and the City" />
    </noscript> 
</a>

JavaScript

window.onload = function(){ if(Modernizr.svg) { $('#img_modernizr_js_remplacement_nojs .header a').html('<img src="logo.svg" width="186" height="235" alt="Logo Geeks and the City"/>'); }else { $('#img_modernizr_js_remplacement_nojs .header a').html('<img src="logo.png" width="186" height="235" alt="Logo Geeks and the City">'); }}

We found this solution at  noupe.com. It uses Modernizr for feature-detection and the noscript-tag as a non-JavaScript-fallback. This solution works if the browser supports SVG or only PNG files and provides the appropriate image.

The SVG image can be linked and it works without JavaScript. It is also accessible. However if JavaScript is disabled, browsers supporting SVG files will just load the PNG file which is not optimal. We don't want to serve images with a lower quality to modern browsers that would be able to display higher quality SVG files.

Since the utilized JavaScript is also not reusable, this solution is not good for automation.

Our solution

Our goals: our logo should be displayed in all browsers, it should be read by screenreaders and it should be displayed even if JavaScript is disabled. Using Modernizr for feature-detection together with the following snippets of code, we have found a method that meets our needs.

HTML

<span style="display: none;" class="fx-svg svg" data-svg="picture.svg" data-bitmap="picture.png">description</span> 
<noscript> <img class="svg-fallback" src="picture.png" alt="description" /> </noscript>

JavaScript

$('.fx-svg').each(function(){ var fxSvg = $(this); var attr = {}; $.each(this.attributes, function(){ attr[this.nodeName] = this.nodeValue; }); attr.alt = fxSvg.text(); attr.src = fxSvg.attr('data-' + (Modernizr.svg ? 'svg' : 'bitmap')); $('<img>') .attr(attr) .show() .replaceAll(this); });

Browsers that have JavaScript enabled and support SVG files will display the SVG file referenced in the "data-svg"-attribute. The browsers won't download both files because we use a <span> tag that is replaced by an <img> tag via our script. Alternative text and a description of the image is simply placed inside the <span> tag and will be used to generate the “alt”-attribute of the <img> tag via JavaScript.

Browsers that have JavaScript enabled but don't support SVG files will display the image referenced in the "data-bitmap"-attribute (it does not have to be a PNG file, any file type/image type can be used).

Browsers that have JavaScript disabled load the image provided in the <noscript> tag.

Note that this script is a work-in-progress. We plan on optimizing its performance, particularly by eliminating the dependency on jQuery and by moving the script closer to the HTML.

Interesse geweckt?

Wir hören gerne zu, wenn Sie Fragen oder Anmerkungen zu diesem Thema haben. Und wenn Sie ein Projekt, ein Produkt, ein Problem oder eine Idee mit uns besprechen möchten, freuen wir uns erst recht über ein Gespräch!