Reliable and Valid SVG Accessibility

If you’re using SVG for more than just icons, such as structured content like a chart or diagram, especially an interactive one, then you need to take a few extra steps to make it accessible. But making an SVG accessible has been a bit of a moving target over the years, usually getting better, but sometimes getting temporarily obscured, because of changes in browser and screen reader support. We’ve specced out most of this behavior, but it doesn’t mean we caught everything, or that it’s implemented consistently or correctly across all screen readers or browsers. And some methods that worked (a bit accidentally) were unintuitive or caused validation errors.

What we want for accessibility are clear, consistent methods for making SVG accessible, that are both reliable and valid across the whole toolchain, from authoring tools to validators and checkers to browsers to screen readers.

4 targets: not reliable, not valid (inconsistent and wrong); reliable, not valid (consistent but wrong); valid, not reliable (inconsistent but right); reliable, valid (consistent and right)
In statistics, we talk about reliability and validity (though “valid” here is a double entendre)

I’m happy to report that now the mechanics of SVG accessibility have never been better. It’s more predictable, more consistent, more interoperable, more standards-conformant, and easier than ever before to make SVG elements accessible to a screen reader.

TL;DR:

For each focusable or interactive SVG element, add a tabindex attribute, a role attribute, and an accessible name (via an aria-label attribute or a <title> element).

That’s it!

Secret traps:

  • Don’t add a tabindex attribute without an accessible name
  • Don’t add a tabindex attribute to the SVG root unless you need to
  • Avoid the title attribute (not to be confused with the <title> element)

The long version, in which we figure out some things that don’t work, some things that used to be necessary but are no longer needed, and just how strangely screen readers can act

I was helping John Gardner from ViewPlus with a new prototype for a simpler interface to load, insert, modify, and save SVG files in an HTML file, in an accessible way. As an incidental part of this, I made a few rough SVG example files that could be loaded and modified; I didn’t pay much attention to the sample SVG files, and just reused some simple SVG accessibility techniques that had mostly worked (and been necessary) at one time. I tested it in VoiceOver on my Mac and it worked fine.

By “worked”, I mean I could use the keyboard to navigate from the HTML form controls to the inline SVG (that is, an SVG file that’s been embedded directly into the HTML code), move to each of the “activatable” shape elements (the ones that had event listeners on them, along with tabindex attributes), hear the title of that element, activate one or more of them with the space or enter keys (which added a stroke to the shape), and navigate back out to the HTML controls to save the modified files. The SVG files were not the relevant part of the prototype; they were just stand-ins for the kind of files users would be loading. They wouldn’t affect the prototype, right? Wrong.

When I was demoing it with John, who uses NVDA and JAWS, he couldn’t navigate to the SVG elements. I could hear his screen reader through the phone. It kept cycling back to the last form element, a button, and repeating the name of that button. Sometimes it would get stuck, and he couldn’t navigate back to the previous form elements. He wasn’t sharing his screen, so I had no idea what was going on, and neither did he. Once in a while, he’d stumble on one of the target elements, but he couldn’t activate it.

Time to step back and debug this very odd behavior.

I don’t have a working Windows machine right now, and I wanted the advice of native screen reader users, so I took to email and Twitter. One of the joys of working in the a11y community is that people are so helpful and friendly. My friends Léonie Watson (@LeonieWatson) of TetraLogical and Jason White of ETS immediately volunteered to help, and started testing the file. And two strangers also stepped up: Kevin Ackley (@ackleyk), an Accessibility Tech Consultant from Nationwide Insurance, and Frank Elavsky (@FrankElavsky).

Kevin messaged me, and I sent him the sample app. A couple minutes later, I got a phone call. He needed to know what the expected behavior was. I walked him through it, and could hear similar problems as those John had. But with a critical difference: Kevin could see that the focus was shifting to the SVG elements, but it was still saying the accessible name from the HTML form control! And he couldn’t activate the elements! What fiendish torture was this? Had the browsers and Windows screen readers reverted to broken SVG behavior? What had 2020 done?!

For a moment, I felt despair. SVG and accessibility are two of my favorite technologies! They should work well together. They had to! I’d helped write the SVG accessiblity specs, for crying out loud! If I was struggling with this, then lots of other people had to be struggling, too. With Kevin patiently agreeing to be my remote eyes and ears and screen reader operator, I went back to basics and started testing combinations of SVG accessibility features. A furious set of permutations of tabindex, <title>, title, aria-labelledby, aria-label, and role followed, with Kevin and I both hacking the source code over a couple of hours. Herein I’ll recount our most salient findings, with 3 problems and 4 best practices.

Context: SVG elements need a tabindex attribute to receive focus

In HTML, most content is wholly or partly text. You usually don’t need to do anything special to make sure the screen reader reads that text out, though you do need judicious use of tabindex on custom controls. By contrast, most SVG content is shapes, which are not keyboard focusable by default. The only elements that are focusable by default are links. If you want a shape element to be interactive or navigable, you need a tabindex attribute with a value of "0". (Historically, SVG used to have a different boolean attribute for making an element focusable, mysteriously called focusable, but we deprecated it for integration into HTML in favor of the legacy HTML tabindex. Alas, you should not use focusable, even if it seems more logical.)

Every focusable element also needs an accessible name, which you can add with the native <title> as a child of the shape element, or with an aria-label attribute.

It’s also worth noting that the alt attribute doesn’t work with inline or standalone SVG elements, not even with the <image> element (the SVG analog to the HTML <img> element). You need to use an aria-label attribute or <title> element to add an accessible name. You can (and should) use the alt attribute for SVG files included in HTML via the <img> element, of course.

Problem 1: tabindex on the SVG root

This was a case of overengineering. Last year, I found a bug in some Windows screen reader / browser combos that you couldn’t navigate to an SVG shape element, even one with a tabindex attribute, unless you also had a tabindex="0" on its <svg> root element. It was like there was a windowless wall, and the root tabindex was the key to the door that let the screen reader inside the room. An annoying bug, but easy to work around. But it turns out, this is no longer necessary in any screen reader and browser combination we tried (VoiceOver / NVDA / JAWS and Firefox / Safari / Chrome). It just adds an unnecessary and possibly disorienting step. Don’t do this anymore, if you ever did.

This might not have been so bad in isolation, but it was devastating in combination with…

Problem 2: no accessible name on the SVG root

An “accessible name” for an element is the text the screen reader reads out when it’s presenting that element to the end user. This the text of the heading or button, or the alt-text of the image. (This is also the text label that someone using voice control uses to active a UI widget.) Without a text description, most SVG elements don’t have an accessible name.

Normally, I always add a top-level <title> element to my SVG files. I skipped it for these throwaway sample files, and I’m glad I did. Because that gave me the chance to discover that not only was the root tabindex unnecessary, but it also revealed some truly weird screen reader behavior. When NVDA or JAWS encounter an SVG element with tabindex="0" and no accessible name, they get confused. Very, very confused. They start repeating the last accessible name they remember (in this case, the HTML form control). Even when they encounter a subsequent focusable SVG shape element with an accessible name, they just can’t get over the trauma of the missing accessible name, and endlessly repeat the last good accessible name they spoke, for any SVG element afterward, whether navigating forward or backwards in DOM order.

And here’s where it gets truly odd. This actually seems to affect the navigation behavior, at least in JAWS. You can no longer reliably navigate back out of the SVG root. (Disclaimer: I didn’t see this for myself, I only heard it, and we were testing behavior fast. It might be that the navigation itself wasn’t affected, but only what was read out. Either way, tricky behavior you want to avoid.)

I’m assuming this is some sort of missing stack reference issue in the screen readers. Don’t fall prey to this one, because it will screw up all your SVG navigation. If you add a tabindex attribute to any SVG element, make sure you give it an accessible name, too.

One we sorted this out, the navigation behavior was smooth and consistent. And Kevin could “activate” the SVG shape element (adding a stroke via JavaScript event handler)… in NVDA. But not in JAWS. If it didn’t work in JAWS, it wasn’t really ready for deployment on the web.

Problem 3: missing role attribute

A little tinkering revealed the problem. I hadn’t added a role attribute to the SVG shape elements. Again, this turned out to be a happy accident (normally, I do add a role and often a aria-roledescription), since it illustrated the necessity of using it.

The role attribute is a feature of of the ARIA specification, which adds or changes the semantics of the element it’s used on. With a role, you can tell screen readers that a <div> is actually a button, for example, and that it should have the same behaviors as a button, such as being focusable and activatable.

Without a role attribute on the SVG shape element, in this case with the value “button”, JAWS would not activate the element, even though it had an event listener on it.

I will be honest: I’m not sure if this is the correct behavior per the specs or not. Either way, I personally think it’s the wrong behavior. This isn’t required for VoiceOver or for NVDA, and I think JAWS should change its behavior here. Consistency between user agents is incredibly important. But this is a pretty easy workaround, and a role is typically useful and adds semantics, so to make sure your interactive SVG elements are activatable, add a role attribute.

As an aside, Kevin pointed out that a few years ago, the way to make SVGs consistently read by screen readers was to follow Léonie’s advice from the article below, which includes using role="img" on the SVG root. Some people leveraged this by removing the role for SVG icons they wanted to be ignored. Even if a <title> were available, if role="img" were not present, the title would not be read. Recently, however, at least some screen readers have changed this behavior, so this hide-the-SVG hack no longer works. Avoid it. Either provide a meaningful accessible name to make it visible to screen readers, or leave off the accessible name to hide it.

I haven’t yet tested if you need to add specific roles (like "button") to make the element activatable, so proceed with caution.

Having solved all the major problems, we next turned to some quick best practices, to distill the minimum of what is necessary, and what is unneeded.

Best Practice 1: no aria-labelledby attribute required

In Léonie Watson’s excellent 2014 article Tips for Creating Accessible SVG, she describes a belt-and-bracers technique that was often necessary at the time. Some screen readers would not recognize the content of the the native SVG <title> element (again, not to be confused with the title attribute inherited from HTML) as the accessible name. To overcome this, Léonie wisely recommended that you use the aria-labelledby attribute to point to the child title, like so:

<path aria-labelledby="button_1" d="…"> 
  <title id="button_1">Shiny red button</title>
</path>

This is effective, but frankly, tedious and verbose to maintain. And luckily, no longer necessary! We found no difference in screen reader / browser behavior between that and the simpler form:

<path d="…"> 
  <title>Shiny red button</title>
</path>

It won’t hurt to continue using the belt-and-bracers technique, but in 2020, it’s doesn’t seem necessary. In fact, pointing aria-labelledby at the <title> element may simply not have any effect. When Frank did some later validation testing for me (more on that below), he found a typo in one of my aria-labelledby attribute values, so it didn’t point to an existing id. It didn’t make a difference in the accessible name generation for that element.

Note that accessibility support for <title> is brand new in Firefox! The Firefox 79 release notes from July 28, 2020 call out new support for exposing the <title> and <desc> elements to assistive technology, resolving a bug reported at least 5 years ago and noted in the great 2016 article Accessible SVGs by Heather Migliorisi (@_hmig).

However, it may be better not to use the <title> element at all. Like the HTML title attribute, modern browsers treat the content of the <title> element as a tooltip, popping up a little infobox after a short delay when you hover over the element. This is often not desirable, and inconsistent since it doesn’t really work on mobiles.

Best Practice 2: use aria-label attribute instead of <title> element

When do you not want the tooltip provided by the <title> element? When you’re providing more complex custom tooltips, especially ones that show immediately rather than requiring a delay. When you don’t want the title of the parent element to be shown for a child element without a <title> element. When it causes visual clutter or distraction on the “empty” space of a chart (imagine having the HTML’s <title> content pop up every time you rest your cursor on the page background).

But you definitely want to add an accessible name. You can use the aria-label attribute for this. It provides an accessible name for that element to the screen reader, without prompting the browser to make a popup. If you want to provide a popup on hover and focus (for consistency), it’s easy to create one using JavaScript, taking the content from the aria-label or data-* attributes.

SVG 1.0 had some great aspirational accessibility features, including text that’s actually text (not just an image of text), and the <title> the <desc> (description) elements. Having <title> as an element, rather than as an attribute, provides a number of advantages, including structured markup content and providing multiple alternative-language versions. These features, their motivations, and some speculations are documented in the W3C Accessibility Features of SVG note by Chaals McCathieNevile (@chaals) and Marja-Riitta Koivunen. But when we conflated <title> with a tooltip, which seemed logical at the time, we muddied the waters. I think this is a decision that should be revisited, and that <title> popups should be removed from browsers, possibly replaced with a hint semantic that works better with keyboards, touchscreens, and assistive technology.

Best Practice 3: avoid title attribute

Many accessibility professionals warn against using the title attribute in HTML. Scott O’Hara has a well-researched and exhaustive article on the varied support for the title attribute that’s worth reading.

In our tests of screen reader and browser behavior, the title attribute on an SVG element acted no differently than the aria-label attribute. Unlike in HTML, the title attribute in SVG doesn’t even produce a popup (while the <title> element does). The title attribute worked perfectly well in all screen readers to generate an accessible name. For better or worse, we don’t have the same complaints in SVG against the title attribute as described in Scott’s article.

However, in Frank’s validation testing, the title attribute was flagged as invalid in the W3C Validator. For the record, I don’t think that’s correct. I see this as more of an oversight in standards or a mistake in the Validator than as a problem with the SVG file. The title attribute, being a global attribute in HTML, should be allowed on any SVG element, too. That said, I still recommend against using it. If it were the only thing that worked, to be blunt, I’d use it whether it validated or not, but luckily, it’s not the only thing that works. The behavior is inconsistent with HTML, it’s unnecessary since it’s no better than using the aria-label attribute, and most importantly, it fails validation rightly or wrongly. Validation errors are a red flag that will be thrown in any accessibility testing or audit, and it will cause hassles without providing value.

In short, don’t use the title attribute in SVG (except perhaps on links which don’t have text content, and even there, you should probably use another accessible name mechanism).

Best Practice 4: validate and test

After Kevin and I wrapped up debugging the problem two or three hours later, I checked my email and saw that both Léonie and Jason had also had similar experiences and come to similar conclusions. Some simple errors in my SVG files caused utter chaos in screen readers, easily corrected but a hassle for screen reader users (and SVG authors like yours truly).

Afterwards, I had a conversation with Frank, who’s done a lot of SVG accessibility testing, too. Both while working at Visa and outside of work, Frank needs to make certain he is following all the regulations and providing an accessible experience, so he has a rigorous testing regime, including using the W3C Validator, aXe, and the Accessibility Insights extension for Chrome. Visa also has open-sourced their accessibility requirements for the community to learn from their tests, procedures, and recommended tools. I’m not specifically endorsing any of these tools; there are loads of other great accessibility tools out there, including Compliance Sheriff and Tenon to name just a couple, but find the tools that work best for your workflow, and use them.

Frank generously validated my code, both in situ (the injected inline SVG) and as the raw SVG files. He found the errors mentioned before (the typo in the aria-labelledby value and the validity errors for the title attribute on SVG elements), and wrote me a concise report via email. His testing came after we’d already solved the problem. I can’t say for certain that it would have pointed me to the solution that Kevin and I arrived at (and which Léonie and Jason verified), but it would definitely have pointed out some of my errors.

Now it’s your turn!

And that’s the kicker. We suffered so you don’t have to. I got lazy, and it caused me stress and lost time, even if I talked with and met some great people through it. If I’d tested myself in NVDA and JAWS, as well as using validation and checking tools, I may not have introduced these problems in the first place. Because I built accessibility in my code from the start (even if it wasn’t perfect), it only took me a short time to recover from the problems we’d found; it would have taken much more time to fix retroactively if I’d been further on.

Please learn from my mistakes. Follow these simple up-to-date SVG accessibility best practices, avoid the nasty problems, don’t get lazy, and test and validate with accessibility tools and real-world screen readers and browsers. SVG accessibility can be easy!

Once again, I want to profoundly thank Kevin Ackley, Léonie Watson, Jason White, and Frank Elavsky for their generosity, friendliness, and technical expertise in helping me diagnose and solve these issues. Without them, it would have been much more frustrating and much less fun.

Accessible Charts with ARIA

Originally published on the Tenon.io blog, on November 25, 2019, in modified form.

Charts, graphs, and other data visualizations are an increasingly common way to convey complex information quickly to your audience. They’re eye-catching, helpful to your users, and they generate lots of traffic to your site.

And they’re inaccessible.

They don’t have to be, but almost all data visualizations are hiding crucial information away from your users with visual impairments. You can fix that, and I’m writing this post to help you along.

My name is Doug Schepers. I worked for the World Wide Web Consortium (W3C), the web standards organization, for a decade writing technical specifications and running working groups. I saw first-hand the disconnect between standards and real-world implementations, and the pain that caused developers and their users. I started W3C’s developer relations activity, before leaving W3C to form a startup doing accessible data visualizations.

One of the projects I worked on at W3C was graphics accessibility, specifically SVG accessibility. I first realized how you could make accessible charts in 2009, and after trying to get something standardized for years, I spoke about it at OpenVis Conf and CSUN in 2013. That got a lot of people excited, and we formed a task force to lay the groundwork, building on ARIA. Standards are slow, but in 2018, W3C published the WAI-ARIA Graphics Module, mostly due to the efforts of Amelia Bellamy-Royds, a dedicated and brilliant SVG expert. Even if you know about ARIA, you probably haven’t heard of the WAI-ARIA Graphics Module, unless you’re especially geeky.

In fact, you might have heard of ARIA, but might not know much about it. Welcome to the club. ARIA is very useful, but widely misunderstood and misused, and it lacks great documentation. In future blog posts, we hope to help clear up ARIA for you, and make using it painless (well, mostly painless, once the numbness sets in).

ARIA basics

At this point, you might be wondering why I’m talking about opera singing. That’s not the kind of aria we usually mean in accessibility circles. ARIA stands for Accessible Rich Internet Applications. It’s a web standard from W3C’s Web Accessibility Initiative (WAI). You’ll sometimes see it called WAI-ARIA.

ARIA is essentially a set of extensions to HTML that help make your web content and controls more usable to people with disabilities. ARIA defines attributes that apply additional semantics and behavior to elements.

  • The 'role' attribute defines the element’s assigned type of user interface component (e.g. a checkbox)
  • The various property attributes describe that component’s individual characteristics of (e.g. whether it’s required)
  • The different state attributes define that component’s current mode (e.g. if it’s checked or unchecked)

ARIA for graphics

So, what does this have to do with charts? Especially a static, non-interactive chart?

Some of those ARIA roles defines significant parts of a document, called landmarks. Landmarks are things like headers, footers, sidebars, navigation, and so on. People using a screen reader often move around these landmarks to build up a complete picture of a document or application, one component at a time.

A chart is just a special kind of document, and it has its own structure and landmarks. For a bar chart, that’s the title, the x-axis and y-axis, and each bar.

chart-diagram-aria-description
Basic accessible SVG chart

The WAI-ARIA Graphics Module defines 3 new roles:

  • 'graphics-document': a document that conveys its meaning through its visual appearance
  • 'graphics-object': a section of a graphics-document that represents a distinct object or sub-component with semantic meaning. A graphical object may itself have nested sub-components
  • 'graphics-symbol': a graphical object treated as a single image component, used to convey a simple meaning or category

Let’s drill into each of these a bit more.

'graphics-document'

This is the parent node of all other ARIA graphics elements. In the case of a bar chart, this is the bar chart itself.

Don’t confuse this with the root node of the document, like the <svg> element (though it might also be that). Each chart should have a single ‘graphics-document’ root, though one document might contain multiple 'graphics-document' elements, such as a dashboard file with several different charts in it.

'graphics-object'

This is an element that contains other parts. It’s a generic structural container element, like an <article> or <section> element in HTML.

This can be used for the x and y axis, for example. They are well-defined areas of the document, which contain other sub-components, like tick marks and scale labels. For this case, the best analogy might be the <thead> element in HTML: a table header, which contains one or more rows each with more or <th> (table header) elements.

'graphics-symbol'

This is an atomic bit of code, usually some mark, icon, shape, or line in a chart, which represents the data point value. In a bar chart, each bar would have a role=’graphics-symbol’ attribute, as would each slice in a pie or donut chart, each line in a line chart, each dot or symbol in a scatterplot.

This doesn’t mean that the data point representation has to be simple, or a single element. If you have a pseudo-3D bar chart, each bar might have elements for the front, top, sides, and shadow, but it should all be encapsulated in a single group (in SVG, a <g> element) with the 'graphics-symbol' role.

And that’s it! If you mark up an SVG chart with these three ARIA roles, it suddenly becomes accessible!

Just kidding, that’s just the beginning. By themselves, these roles don’t have any properties or states; in other words, they don’t have any inherent behavior. But what they do is to identify each part to the screen reader, so it knows how to categorize and characterize them to the end user.

Exposing elements to the user

Once you have the parts of the chart document marked up, it’s getting more accessible. I say “more accessible”, but that’s not true yet, because they are still invisible to screen readers. By default, most SVG elements are hidden from screen readers, the exceptions being links and textual elements. You can make them keyboard-navigable by adding tabindex='0' to each component.

Adding value

What’s the best way to add value for a screen reader user? By literally adding the value of the data point to its representing element. If you have an element that draws a bar, with the height showing the value, then you simply include that value as text as well; think of it as really tiny alt-text. In SVG, there are four ways to do that: with a <text> element; with a <title> element; with an 'aria-label' attribute; or with an 'aria-labelledby' attribute pointing to an element that holds the value (such as a <text> or <title> element).

<text> element

The <text> element (and its optional child element, the <tspan>) is how you render text to the screen in SVG. Like in HTML, this text can be selected, copied, and searched for. This is ideal if you want the value to always be shown, as a label on a bar or pie slice. To associate it with the data point element, group it in the same <g> element, or give it an 'id' attribute and point to it with the 'aria-labelledby' attribute.

<title> element

The <title> element in SVG is like the ‘title’ attribute in HTML. It’s a hidden metadata value that only appears on hover (note that it doesn’t appear on focus, so it’s not as accessible as it should be). You can use this if you only want the value to be shown on hover. To associate it with the data point element, put the <title> as a child of the data point element or its parent <g> element, or give it an 'id’ attribute and point to it with the 'aria-labelledby' attribute. (Note that for legacy browser support, it might be best to use both of those techniques.)

'aria-label' attribute

This is pretty straightforward. Just put the value in the 'aria-label' attribute, like this:

<rect aria-label="4" … />

'aria-labelledby' attribute

This is a tad more complicated, but there are reasons you might want to have this level of indirection, such as when you’re pointing to a value that appears elsewhere and don’t want to duplicate it. You give the referred element an ‘id’ attribute value, and use that as the value for the ‘aria-labelledby’ attribute, like so:

<text id="bar-1-value"></text>
<rect aria-labelledby="bar-1-value" … />

Any one of these techniques will cause the screen reader to read out the value. Voila! Now, the chart is well on its way to being about as accessible as a table. The user can use a keyboard to get to each component, and step through each bar in turn to hear the values.

These are the bare essentials for making an accessible SVG chart. It’s worth noting that that the WAI-ARIA Graphics Module isn’t SVG-specific; you could do the same with HTML+CSS charts. But SVG is the markup of choice for charts these days.

Once more, with meaning

Okay, so now the user can get at each data point, and get its value. Just like in a data table. But a chart isn’t a data table, and not each data point is the same. When a blind or low-vision person is talking to a fully-sighted person about a chart, they should be able to use the same terms to avoid confusion. They should know it’s a bar in a bar chart, a slice in a pie chart, a line in a line chart. They should know it’s the y-axis or the x-axis or the legend. They should know what kind of chart it is.

ARIA doesn’t have specific roles for different kinds of data points, or parts of a chart, or chart types. But what it does have, starting in ARIA 1.1 (finalized in December 2017), is the 'aria-roledescription' attribute.This attribute lets you provide a natural-language equivalent for an ARIA role.

As an example, the following element would be read by a screen reader as something like, “bar element”, instead of “graphics-symbol element”:

<rect role="graphics-symbol" aria-roledescription="bar" 
  tabindex="0" 
  x="70" y="20" width="25" height="40"></rect>

In SVG, this is a <rect> element, which draws a rectangle on the screen. But to a screen reader, it’s now a bar element, and that’s how it’s communicated to the user. With 'aria-roledescription', you can call a shovel a shovel.

Does this work in browsers and screen readers?

Standards are one thing, and implementations in “user agents” (browsers and screen readers) is another story. Fortunately, these features have pretty good support. That raises the question, what does “support” look like in the case of ARIA, and for these features specifically? Especially when they don’t have any defined behavior?

To answer that, we need to step back and look at how Assistive Technology (AT) like a screen reader works. In short, the browser downloads the document file, then creates a DOM (Document Object Model) tree, and visually renders the result of that DOM tree; that’s all commonly understood by web developers. But less commonly known is that from the DOM tree, the browser also creates an accessibility tree (also called the accessibility object model, or AOM), which is a subset of the DOM tree that is specifically relevant to AT. The browser then exposes that accessibility tree to its analog in the operating system, the platform-specific Accessibility API (each unique to that OS). The OS Accessibility API in turn shares that information with the AT, such as a screen reader, which is finally rendered (as speech, Braille, or some other form) to the end user.

So, this means that the question of user agent support becomes, “Does the browser translate this element correctly to its analog in the platform Accessibility API? And does the screen reader recognize and announce that role?” That’s something testable.

This translation is detailed in the Graphics Accessibility API Mappings, a companion spec to the WAI-ARIA Graphics Module. And that specification has a test suite, which tells us how well it’s supported. At the time of publication in October 2018, all browsers on all OSes supported these features, with the exception of the 'aria-roledescription' attribute in Chrome on MacOS. Since then, my testing shows that that also seems to have been implemented.

Full disclosure

I have noticed glitches in browser and screen reader support. This is true of ARIA support in general. There is a legitimate question on how we best serve our readers: Do we take a conservative approach, and only publish content that is rock-solid? Or do we recognize that if we don’t create valid content that pushes those boundaries, browser and AT vendors don’t have enough incentive to improve their support? That’s a decision that each publisher needs to make. For my part, I favor the latter, to counter the chicken-or-egg debate. No progress happens without active effort.