Tips for Creating Accessible SVG

Léonie Watson
Another form of accessible data - Beautiful, bronze, touchable, 3D map of Deventer, Netherlands

A different form of accessible data – a 3d
topographical map of Deventer, Netherlands.
Photo: Ronald Rugenbrink

Scalable Vector Graphics (SVG) exists in a quantum state of accessibility. Which is to say that SVG is both accessible and inaccessible at the same time.

Happily, there is no SVG uncertainty principle.

We know which aspects of SVG are accessible to whom, which are not, and what we can do to improve both.

To recap: SVG 1.0 was released by the W3C in 2001. SVG 1.1 came along in 2003, and SVG 1.1 2nd edition in 2011. SVG 2.0 is currently a W3C working draft.

SVG 1.1 includes several features that lend themselves to accessibility, but SVG 2.0 will take accessibility to another level. Whilst SVG 1.1 has good cross-browser support, SVG 2.0 is still too early in its lifecycle for browsers to have implemented support.

This article looks at ways to make SVG 1.1 content as accessible as possible, with glimpses into the possibility space of SVG 2.0 accessibility.

Tip #1: Use SVG

This may seem like a strange thing to say, not least in an article that’s about SVG to begin with.

The fact is that one of SVG’s most compelling characteristics is also one of its most accessible. SVG content is scalable, and more to the point it scales without any reduction in visual quality.

This makes it extremely versatile from a development point of view, but it also means that people with less than 20/20 vision can enjoy crisp and clear images no matter what screen size and resolution they use.

Tip #2: Use inline SVG

The best way to make SVG accessible to Assistive Technologies (AT) like screen readers and speech recognition tools is to put it directly into your HTML. It’s much cleaner (in code terms) to do this with HTML5 than it was with HTML4.x, because the HTML parser automatically switches mode and puts the SVG elements and attributes into the correct namespace.

In other words, if your HTML uses the HTML5 doctype, you don’t need to include a namespace declaration in the <svg> tag.


<svg version="1.1" width="300" height="200">...</svg>

Using other methods to incorporate SVG produces less reliable accessibility results, or limits the information available to AT.

For example, SVG content pulled in via the <embed> or <object> elements isn’t as well accessibility supported by browsers as inline SVG, and SVG pulled in via the <img> element is limited in the information that can be exposed to AT.

SVG 1.1 supports DOM 2, so information about the SVG can be programmatically examined and manipulated. Scraping the DOM isn’t an efficient way for AT to obtain information though. It’s much more efficient when information about the DOM is exposed by the browser’s accessibility API. All modern browsers have an accessibility API providing properties and methods that can be queried by AT.

For the purposes of this article, we'll focus on the following browser/screen reader combinations: Internet Explorer 11, Firefox 28 and Chrome 30 on Windows, with Jaws 15 and NVDA 2014.1. Safari 6 on iOS/OSX with VoiceOver, and Chrome 30 on Android with TalkBack.

Of these browsers, only IE and Firefox expose the role of the <svg> element through their accessibility API at this time. IE identifies it as a graphic, and Firefox as a diagram. Of the screen readers used with these browsers, only Jaws with IE utilises this information to indicate there is graphical content on the page.

The good news is that there is something we can do about that. Hold that thought, we’ll come back to it later on.

Tip #3: Provide a title

The SVG <title> element provides a human readable name for the SVG content, or a component within it. The <title> element must be the first child of its parent element, which may be one of the SVG container elements or graphics elements, or the <svg> element itself. The SVG 1.1 specification specifically mentions the importance of providing a title for the <svg> element.


<svg version="1.1" width="300" height="200">
<title>Green rectangle</title>
<rect width="75" height="50" rx="20" ry="20" fill="#90ee90" stroke="#228b22" stroke-fill="1" />
</svg>

The content of the <title> element isn’t rendered visually by default (although it can be styled to do so). It should be exposed through the browser’s accessibility API though, specifically to give its parent element an accessible name.

In the previous example, the content of the <title> element gives the <svg> element its accessible name, enabling screen readers to differentiate this chunk of SVG content from any other on the page.

To put it simply, the <title> element provides an alternative text description of the SVG content. Think of it in the same way you would the alt attribute on the HTML <img> element.

At the moment only IE and Firefox correctly expose this information, and only Jaws in IE makes use of it. We can improve these odds though.

When ARIA 1.0 is present in the HTML code, it causes the browser to update the information it makes available through its accessibility API. ARIA has good support across browsers and screen readers (although no other AT at this time), so it can help bolster the accessibility of SVG content for blind and partially sighted people.

ARIA support is introduced officially into the SVG 2.0 specification, but it is still possible to use ARIA with SVG 1.1 content. Some examples in this article will raise a flag when you validate your HTML, but it’s a reasonable exception to make.


<svg version="1.1" width="300" height="200" aria-labelledby="title">
<title id="title">Green rectangle</title>
<rect width="75" height="50" rx="20" ry="20" fill="#90ee90" stroke="#228b22" stroke-fill="1" />
</svg>

The aria-labelledby attribute in this example re-enforces the relationship between the <svg> and <title> elements.

In other words, it ensures the content of the <title> element is recognised as the accessible name for the SVG content.

The effect is that now Chrome and Safari also expose “Green rectangle” as the accessible name for the SVG content, and screen readers including VoiceOver, TalkBack, Jaws and NVDA all make use of it in at least one browser.

Tip #4: Provide a description

The SVG <desc> element is similar to the <title> element in many ways. It doesn’t render visually by default, but it is intended for human consumption. Instead of providing a name for its parent element, it provides a description. In accessibility terms, the <desc> element is where you provide more detailed information about the SVG content than the <title> allows.


<svg version="1.1" width="300" height="200">
<title>Green rectangle</title>
<desc>A light green rectangle with rounded corners and a dark green border</desc>
<rect width="75" height="50" rx="20" ry="20" fill="#90ee90" stroke="#228b22" stroke-fill="1" />
</svg>

Browser accessibility support for the <desc> element is about the same as for the <title> element. The content of the <desc> element should be exposed as the accessible description for the containing element, but again only IE and Firefox do the honours.

ARIA comes to the rescue here too, but not in the way you might think. The obvious solution should be to use the aria-describedby attribute to –re-enforce the relationship between the <svg> and <desc> elements.


<svg version="1.1" width="300" height="200" aria-labelledby="title" aria-describedby="desc">
<title id="title">Green rectangle</title>
<desc id="desc">A light green rectangle with rounded corners and a dark green border</desc>
<rect width="75" height="50" rx="20" ry="20" fill="#90ee90" stroke="#228b22" stroke-fill="1" />
</svg>

Although the browser’s now expose the correct information through their accessibility API, screen reader support is much less consistent. Jaws and NVDA with IE, VoiceOver with Safari and TalkBack with Chrome all make use of the accessible description, but Jaws and NVDA with Chrome and Firefox do not.

For the time being a workaround is to make the aria-labelledby attribute work a little bit harder.


<svg version="1.1" width="300" height="200" aria-labelledby="title desc">
<title id="title">Green rectangle</title>
<desc id="desc">A light green rectangle with rounded corners and a dark green border</desc>
<rect width="75" height="50" rx="20" ry="20" fill="#90ee90" stroke="#228b22" stroke-fill="1" />
</svg>

This isn’t ideal because the name and description are conceptually different things, and serve different purposes. In the interests of making relevant information available as widely as possible this approach does the trick though, albeit through slightly gritted teeth.

Tip #5: Use text

Text is generally accessible however it’s presented, with the exception of raster images (png, jpg etc.). Text in these images can’t be detected by screen readers (or search engines), and it can’t be resized for easier reading comfort. Even when zoomed, the quality of text in images reduces noticeably, and the UX for people with low vision deteriorates right along with it.


<svg version="1.1" width="300" height="200" aria-labelledby="title desc">
<title id="title">Green rectangle</title>
<desc id="desc">A light green rectangle with rounded corners and a dark green border.</desc>
<rect width="75" height="50" rx="20" ry="20" fill="#90ee90" stroke="#228b22" stroke-fill="1" />
<text x="35" y="30" font-size="1em" text-anchor="middle" fill="#000000">Website</text>
</svg>

The SVG <text> element makes text in graphical content highly accessible. The content of the <text> element is rendered as plain text by the browser, so it’s available to screen readers, and because it’s SVG it can be resized proportionately with the graphical content for the benefit of anyone with less than 20/20 vision.

You still want to make the default text size comfortable to read, but beyond that people can adjust the SVG to suit themselves.

Tip #6: Make it focusable

If your SVG contains content that is interactive, you’ll need to make sure it can take keyboard focus. As with HTML, the best way to do this is to use an element natively designed to take focus in the first place.


<svg version="1.1" width="300" height="200" aria-labelledby="title desc">
<title id="title">Green rectangle</title>
<desc id="desc">A light green rectangle with rounded corners and a dark green border.</desc>
<a xlink:href="http://example.com">
<rect width="75" height="50" rx="20" ry="20" fill="#90ee90" stroke="#228b22" stroke-fill="1" />
<text x="35" y="30" font-size="1em" text-anchor="middle" fill="#000000">Website</text>
</a>
</svg>

The SVG <a> element should mean that keyboard users can focus on the link when using the tab key to move through the content. All the browser/screen reader combinations mentioned in this article all support that behaviour.

Tip #7: Give it a role

Remember that thought you were holding? We’ve arrived at the point where we can solve the problem of the <svg> element role not being correctly exposed by all browsers.

All elements have a role – it identifies the purpose that element fulfils. The role of an element should be exposed through the browser’s accessibility API, but you’ll recall that only IE and Firefox correctly exposed the <svg> element to AT, and only Jaws with IE utilised that information.

The ARIA role attribute can be used to force the correct role to be exposed to screen readers. In the case of the <svg> element we can apply the img role.


<svg version="1.1" width="300" height="200" aria-labelledby="title desc" role="img">
<title id="title">Green rectangle</title>
<desc id="desc">A light green rectangle with rounded corners and a dark green border.</desc>
<rect width="75" height="50" rx="20" ry="20" fill="#90ee90" stroke="#228b22" stroke-fill="1" />
</svg>

This improves the browser odds considerably, with IE, Firefox, Chrome and Safari all exposing the role correctly. Screen reader support is still a little inconsistent, but it too improves, with the exception of Jaws and NVDA in Chrome, and Jaws in Firefox. VoiceOver with Safari, TalkBack with Chrome and Jaws and NVDA with IE all now recognise there is graphical content on the page.

It may not always be appropriate to use the img role on the <svg> element though. It's fine if your SVG content is purely graphical, but if it contains interactive content, a different approach may be needed.


<svg version="1.1" width="300" height="200" aria-labelledby="title desc">
<title id="title">Green rectangle</title>
<desc id="desc">A light green rectangle with rounded corners and a dark green border.</desc>
<a xlink:href="http://example.com" tabindex="0" role="link">
<rect width="75" height="50" rx="20" ry="20" fill="#90ee90" stroke="#228b22" stroke-fill="1" />
<text x="35" y="30" font-size="1em" text-anchor="middle" fill="#000000">Website</text>
</a>
</svg>

In this example the link role has been applied to the SVG <a> element. Now all browser/screen reader combinations we've looked at in this article recognise that the link is a link, with the exception of NVDA in IE.

Tip #8: Create an alternative

Whilst there is much you can do to bolster SVG accessibility with ARIA, native accessibility support for SVG amongst browsers and AT is still evolving. SVG 2.0 will change this, but for now we need to be realistic about the current state of affairs.

When you create something in SVG it’s a good idea to provide the same information and/or functionality in a format that has better accessibility support. If your SVG content is purely graphical in nature, using ARIA to enhance the <title> and <desc> elements will do the trick.

If your SVG contains anything more complex or interactive, then you’ll need to think about presenting it in different ways. For example information presented in an SVG graph might also be provided in an HTML table, perhaps with a choice of views offered through a tabbed interface.

In some respects, SVG is the forgotten technology of the web. It has enormous practical and creative potential though, and its accessibility potential is just as strong. This article suggests steps you can take to make your SVG 1.1 content more accessible, but the really exciting stuff is coming with SVG 2.0.

If you’re interested in helping us make this happen, you can join the W3C Accessible SVG community group, or get involved with the W3C SVG working group.

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • Dee-Rest

    I’d never thought about SVG in terms of accessibility, but it makes so much sense. This is a great framing article for the subject. Thanks Leonie.

    • Léonie Watson

      Thanks :)

  • SerzN1

    aha.. aha

    just it’s not working correctly cross browser

    people make examples with 1 rect…. oh well

    but just text positioning can drill the brain

    • Alex Walker

      Agree that text positioning is not one of SVGs more elegant aspects.

  • Malachi

    Thanks. One note though.. the image at the top talks about Diventer. That needs to be Deventer…

    • Alex Walker

      Fixed. Thanks for the heads up.

  • chriscoyier

    If the entire <svg> is a link, is it acceptable to wrap it in an anchor? Or best to have the link be within?

    • Alex Walker

      Interesting question, Chris. I’m checking with Léonie for that.

    • Léonie Watson

      Sorry for the radio silence Chris.

      I’d be inclined to pull in the SVG using the img element, to create a standard HTML graphical link. It’ll be more backwards compatible if nothing else.

  • Mike

    What are the purpose of the id’s on and ? Are they neccesary for, aria-labelledby=”title” aria-describedby=”desc”, to work? Can I skip those id’s?

    • Léonie Watson

      Yes, the id attributes are needed to create the association with the aria-labelledby attribute on the desc element. When a screen reader encounters the SVG element, it finds the aria-labelledby attribute, then goes looking for the label(s) it’s associated with.

  • Petit Paul

    Hello, in your code, I believe stroke=”228b22″ should be stroke=”#228b22″.

    • Léonie Watson

      You’re right. Missed that one, thanks for the heads up. Hopefully Alex can put it straight.

  • Alex Walker

    Hi Tiffany,

    Are you talking about accessibility concerns with SVG CSS backgrounds or just the method in general?

  • http://matthill.co/ Matt Hill

    Lots of great accessibility techniques here, thank you. I’m trying to get much better at making my work fully accessible.

    I did notice however that the example code isn’t valid. If I run your example through the W3C validator, it claims it’s an error to have the “aria-labelledby” and “role” attributes on an SVG. Is this technique not valid?

    Thanks in advance for any extra information you can offer.

    • Léonie Watson

      Thanks Matt.

      For the time being the W3C validators (even the Nu validator) don’t recognise ARIA with SVG. It’s possible this might not happen until SVG 2.0 is a bit more advanced and/or the ARIA to SVG mapping specification is available.

      It was like this with ARIA and HTML5 for a time, but the general thinking was that the benefits of using ARIA outweighed the need for perfect validation. It’s the same now with SVG.

      HTH.

  • Alex Walker

    Interesting. Leonie, would have the last word on this one, but I can’t see how a screen readers would be able to have any access to CSS background image.

  • Frann Leach

    OK. I’m a bit confused. I can’t see any value in making a green rectangle accessible. The blind won’t have any additional information, the visually impaired will see it anyway without a title.

    I have bought vector graphics. I’m more interested in how to use those images, not boxes that I can build anyway without svg.

  • Léonie Watson

    Screen readers won’t recognise any CSS background images, regardless of the graphic format being used. With a couple of exceptions, screen readers ignore the presentation layer completely and rely on information being exposed via the DOM and/or accessibility APIs.

    If your background image is SVG, there’s no need to include the ARIA mentioned in this article. It won’t be rendered by the browser in a way a screen reader can make use of, so it’ll just bloat your code. It does mean that you’ll need to provide a text alternative to the background image that screen readers can access though.

    A wider point about background images is that people using Windows high contrast mode and Internet Explorer won’t be able to see them either. This coupled with the screen reader use case, means it’s not a good idea to include important information only via a background image.

    HTH.