Accessible SVG flowcharts

The accessible SVG line graphs post explains how to use ARIA table semantics to make that form of data visualisation accessible to screen readers. This article uses the same ARIA based approach to make a screen reader accessible SVG flowchart.

The example comes from the W3C Process document, and a flowchart that describes the process of taking a specification from its First Public Working Draft (FPWD) through to official W3C Recommendation (Rec). The original SVG can be found in the W3C Process 2015 document, and a revised version (with a first attempt at accessibility) is in the W3C Process 2017 document.

SVG lacks the semantics to express structures like line graphs, bar charts, or flowcharts, and so SVG data visualisations are difficult for screen reader users to understand. The structure of a flowcart can be represented as a series of nested lists, so we can use ARIA to impose these semantics for the benefit of screen reader users.

The following ARIA roles and attributes were used for the W3C flowchart:

Adding the ARIA

The first step was to create the skeleton structure of the flowchart, using the g element as the base. Here’s a fragment:

<g role="list">
  <g role="listitem"></g>
  <g role="listitem">
    <g role="list">
      <g role="listitem"></g>
      <g role="listitem"></g>
  </g>
</g>

Once the existing SVG content had been moved into the new structure, the img role was applied to the first child element inside each link (more on the links later), and the title element used to give the element its accessible name, to encourage screen readers to recognise the listitems.

The aria-hidden attribute was then used to hide the text element from screen readers (because it duplicated the accessible name of the title element).

<g role="list">

  <!-- FPWD -->
  <g role="listitem">

    <a xlink:href="#wd-1">
      <rect role="img" fill="white" y="122" width="57" height="45">
        <title>First Public Working Draft (FPWD) - Exclusion opportunity</title>
      </rect>

      <text font-size="8">
        <tspan aria-hidden="true" y="132" x="0">First Public WD</tspan>
        <tspan x="0" y="152">WG decision</tspan>
        <tspan x="0" y="162">Director's approval</tspan>
      </text>

      <path d="M0,140h53" fill="none" stroke="#000"></path>
      <polygon points="47,136 57,140 47,144"></polygon>
    </a>
  </g>

  <!-- WD -->
  <g role="listitem">

    <a xlink:href="#cr-1">
      <ellipse role="img" id="wd-1" ry="18" rx="38" cy="140" cx="97" stroke="black" fill="#fff">
        <title>Working Draft (WD)</title>
      </ellipse>

      <text aria-hidden="true" font-size="14" y="144" x="97" text-anchor="middle">WD</text>
    </a>

    <g role="list">

      <!-- New WD -->
      <g role="listitem">

        <a xlink:href="#wd-1">
          <g role="img">
            <title>Publish a new Working Draft</title>
          </g>

          <text font-size="8"><tspan x="30" y="92">WG Decision: review needed, or</tspan>
            <tspan x="40" y="100">No change for 6 months</tspan>
          </text>

          <path d="M78,124C73,114 79,104 97,104 108,104 115,108 117,114" fill="none" stroke="black" stroke-dasharray="6 1"></path>
          <polygon points="120,114 116,124 114,113"></polygon>
        </a>
      </g>

      <!-- Advance to CR -->
      <g role="listitem" fill="#060">

        <a xlink:href="#cr-1">
          <g role="img">
            <title>Advance to Candidate Recommendation</title>
          </g>

          <text x="138" y="134" font-size="8">Director's approval</text>

          <path stroke="#060" d="M135,140h81"></path>
          <polygon points="211,136 221,140 211,144"></polygon>
        </a>
      </g>
    </g>

    ...
  </g>

...
</g>

Navigation

The SVG flowchart now has a semantically meaningful structure, but to really understand the data in a flowchart, it’s helpful to be able to navigate between siblings, as well as to follow a parent/child path through it.

The flowchart in the W3C Process document attempts to provide this form of navigation using links. This makes it possible to navigate directly between the siblings in the first layer of the flowchart (using the tab key), but is also introduces some different problems:

  • The links have no perceived affordance; this may be ok for pointer device users who do not need the links, but not for sighted keyboard users who do. The visual affordance of the links could be improved, but that creates a different problem; should a pointer device user click/tap on the link, the shift of focus would be so slight as to be unnoticeable and the link would appear to be broken.
  • The destination of the link is not indicated to anyone. This could be resolved by separating the link from the item, but this reduces the usability of navigating from one sibling item directly to the next by introducing additional keystrokes.
  • It isn’t particularly scalable. Without some way of knowing when a press of the tab key moved focus out of one branch to the next, it would be too easy for keyboard users (sighted and not) to get lostt in a flowchart with multiple branches.

Although the keyboard experience still leaves something to be desired in SVG, adding ARIA goes some way to making the content more usable by screen reader users. The ARIA enabled version is included in the W3C Process 2018, and a demo version is also available. If you find any issues, you can file them on Github.

8 comments on “Accessible SVG flowcharts”

Skip to Post a comment
  1. Comment by Rafal

    Can I link to another part of the svg image? I would like to create a navigable branched flowchart. If an answer to a question is “yes” then the next question would be read. If the answer is “no” a different question will be asked.

    I tried using a href name and a xlink:name but the screen reader (Voice Over) doesn’t jump to next questions when I click link.

    1. Comment by Léonie Watson

      Links within an SVG can be problematic. Part of the problem is that browsers do not always handle internal page links well to begin with.

      One possibility is to use tabindex=”0″ on the target element. That might force both keyboard focus and screen reader focus to the right part of the page.

      1. Comment by chaals

        When I made this, the problem was that Safari didn’t follow internal links in SVG (other browsers do, *IF* I recall correctly)

        1. Comment by chaals

          What I would like is to be able to use something like aria-flowto or whatever it is called with multiple possible destinations (that was also a feature xlink was meant to offer, but I don’t know if anyone ever implemented it)…

            1. Comment by Rafal Drewnowski

              So I did try aria-flowto and it allowed me to navigate different branches using Chrome and Safari. It didn’t work in Firefox.

              I will keep experimenting with other aproaches and let you know how it went.

              Here is my first example: http://rafal.design/how-to-inspect-windscreen.html

              1. Comment by Rafal Drewnowski

                I used VoiceOver on Mac obviously

  2. Comment by Brennan Young

    I’m also working on an accessible SVG flowchart, so this article is something of a touchstone.

    First thing to mentions is that SVG’s wonders are matched only by its infuriating gotchas, especially between browsers. I live in fear that the whole effort will be scuppered by some missing feature. In particular, there is no multiline text, which makes text layout horribly fragile, and we’re about to explore using foreignObject containing HTML instead of text and tspan.

    The other thing is that flowcharts fall between two stools. They are not really ‘documents’ and they are not really ‘applications’.

    At first we just treated them as images, but the requisite alt text quickly became too long and confusing. Editing it down without losing the essentials proved extremely difficult. I suppose that if flowcharts could be described easily in prose, there would be no need for them in the first place. Prose does not have ‘branches’. A closer model in human-readable text is those “choose your own adventure” books. The medium is the message.

    I’m interested to see how you used a xlink here, so that focus() works predictably. I will certainly borrow this technique. The info given about roles is also very useful. Thank you so much!

    We also opted for TAB to move between boxes, because this is the very key we expect to use to navigate any accessibility tree. It also provides an obvious ‘backwards’ convention in SHIFT-TAB. So far so good.

    When it comes to branching, we opted for the following, which is different from your solution:

    Arrows/pathways ‘belong’ to the box that they *exit*. (In markup, they are contained inside the same g element, and are therefore ‘children’ of the box). When you focus on a box, the outgoing arrows (and their labels) are all ‘in focus’ at once.

    When a box has more than one ‘exit’ pathway, you select the specific output using arrow keys. (I chose left and right). When a box first comes into focus, we autoselect the ‘first’ (in markup) of these exit pathways.

    The selected pathway is highlighted with the same stoke/fill as used for the outline of the boxes. The text content of the path label is inserted into an aria live region when it gets selected. Its id might also gets inserted into the aria-activedescendent attribute of the parent box, but we’re not sure about that.

    There is a g element wrapping each pathway which consists of one or more arrows (currently implemented as polygons) and an accessible label. The g element has class=”pathway”.

    The pathway element includes both data-destination=”someBoxID” (HTML5) and ourNamespace:destination=”someBoxID” (XML). These custom attributes can be used to hook up branched navigation even when it deviates from the markup order.

    Why both kinds of data attribute? Well, sometimes we imagine our flowchart to stand alone, sometimes we imagine that it will be inlined into HTML. Strictly speaking only one is needed at a time.

    Pressing TAB gives focus to the element indicated in the destination attribute. Some browser’s SVG implementation have no support for focus() so we are still chewing on that.

    Our solution feels very natural. I’d really like to share it with you and your readers on codepen or some such because feedback would be wonderful, although I need to iterate a little more on it, and either get permission from our content partners. Maybe I can remove any ‘sensitive’ content and post a demo, but time is short.

    Finally, we have ambitions to create (or find) a small declarative language which will allow us to define the text contents of the boxes (which in our case need to be localized in different languages), how many pathways each box has, and where those pathways lead. Then let some script do the heavy lifting of specifying the coordinate data. There might also be a need to distinguish different kinds of box (semantics!), traditionally represented by different box shapes.

    OK, this got long. Suffice to say that flowcharts deserve more attention from the accessibility developer community, some ‘best practice’ pattern work, and perhaps even some new w3c-sanctioned aria roles!

    I hope to be back at some point with a code demo to share. Thanks again for your efforts!

Comment on this post

Will not be published
Optional

This site uses Akismet to reduce spam. Learn how your comment data is processed.