3

I have an SVG tree graphic which I'd like to make accessible to users of NVDA and similar.

Each node in the SVG graphic is coded like this:

<g class="node" >
<foreignObject tabindex="0" focusable="true" aria-label="I want this read by screen readers such as NVDA..." class="nodestyle">...and I'd like this read out as well.</foreignObject>
</g>

At the moment when I tab to each node, Chrome just reads out the text in the foreignobject, and Edge Chromium only reads out the aria-label text in the g. I've tried using title, label, etc in both the g and foreignobject, but I can't get either browser to read out both pieces of text. Can anyone suggest how I can achieve this, if it's possible at all?

I don't want to do hacky things like putting in extra text and then hiding it with CSS.

TylerH
  • 20,799
  • 66
  • 75
  • 101
Paddy UK
  • 45
  • 6
  • 2
    What are you trying to achieve? i.e. why have a node that contains text have additional info for screen readers. I ask because there may be a better way to structure your SVG. Oh, and check out `aria-labelledby` as that would allow you to do what you want with a slight restructure. I will post an answer once you give me the use case you have so I can check you are trying to work around a problem the wrong way (and end up offering bad advice). – GrahamTheDev Jan 17 '20 at 16:27
  • Thanks for comment, @GrahamRitchie. I've made an interactive decision tree. Clicking or pressing Enter/Space on nodes opens/closes sub-branches. When tab is used to navigate nodes, focus jumps between nodes on different branches. For blind users, I want nodes to read out something about the parent node so they know where they are in the tree. Otherwise they may navigate to a node saying "No" with no context of what they're responding to. I *could* re-word all the questions, but my brief requires minimal wordiness. Page example: www.creativemedia.org.uk/interactive-trees/template.html – Paddy UK Jan 20 '20 at 09:45
  • Hi Paddy UK, confused by the link you added, might be being stupid but I can't find a decision tree, can you link the page it is on or point me to the exact spot on the page. – GrahamTheDev Jan 20 '20 at 17:53
  • Hi @GrahamRitchie, I'm sorry if I've caused confusion. The code in the link is what I'm asking about, but it's just got dummy data in. I may be misusing the term "decision tree"; I'm meaning a branched structure of questions/answers that lead the users to a particular conclusion. I've updated the first node to actually be a question now. – Paddy UK Jan 20 '20 at 18:15

2 Answers2

1

I have been doing something quite similar, although I don't have any open/close hide/show behavior.

This is very much not a solved problem, so I am curious about any work done in this space, and I hope you're up for further correspondence! Do check this article. I think it's part of any proper solution. This one is worth a look, too.

I've tried many things, also settling on SVG with foreign object, and tabbing to navigate. Even implemented a couple of different mechanisms to choose branches.

The tricky thing is choosing branches. There's an attribute called aria-flowto which takes one or more 'destination' id as a value, but it has very poor support, and there are no recommended idioms for selecting amongst them. (It can be made to work with javascript, however).

One of my attempts uses javaScript to copy the contents of the boxes in to an aria-label attached to the element with tabindex=0 on it. This works pretty well, but does not give any of the affordances of 'browsable' content. Again, announcing branches is a challenge.

If you want the markup inside the foreignObject to be browsable using semantic affordances such as headings, you'll probably have to use role=document, which many a11y community members will no doubt warn you against because it's tricky. I've been able to get role=document working fine in HTML, but haven't yet integrated it with SVG. I don't yet know if it will play well with the WAI-ARIA Graphics Module roles.

TylerH
  • 20,799
  • 66
  • 75
  • 101
brennanyoung
  • 6,243
  • 3
  • 26
  • 44
  • I'll count Graham's response as an answer - thanks Graham; the W3C tree looks really useful (if a bit less pretty) as a way of creating a blind-friendly branching question/answer structure. – Paddy UK Jan 27 '20 at 15:53
1

Sadly with the example you have this is going to be very difficult to implement (not the labelling part but accessibility in general due to the document structure).

First thing you need to do is fix the DOM order of the SVGs - the first node you land on is 'no' which is confusing and fixing the DOM order is a lot easier than trying to manage tabindex.

The next thing is that you need to show that activating an item (i.e. 'yes') has an effect of loading more options.

For this I would follow conventions of collapsible content - this accordion example should help you understand how to use aria-expanded and aria-controls correctly. (but only use it for understanding those concepts, it isn't the right solution for your problem.)

Next you need to consider letting a user know what options have now been presented to them. The simplest way to do this is to wrap the SVGs in an <ul> as then a screen reader will let them know how many items there are to choose from (within the expanded section).

With that in mind you should look into how a treeview is structured as that will give you the closest example of how to structure complex nested structures.

Also look at this file explorer tree view example which is similar to see that with correct nesting you do not need to worry about labelling too much. (as you can just use the <title> property of your SVGs as the content if you find the plain text is not read out correctly).

What you will notice in the above examples is that the 'parent node' text is actually contained within the <li role="treeitem"> so that when you select a sub-item it reads both the parent and the selected item out together automatically.

Trying to do all of the above with just the SVGs will cause you numerous headaches with workarounds (i.e. you could use aria-labelledby with multiple IDs on child items to achieve what you originally asked but then you have lots of maintainability issues) so I would recommend looking at trying to copy a treeview structure and keep your SVGs simple.

The final advantage of the treeview method is that users will be familiar with how to control the treeview (arrow keys and space to expand / collapse) so you don't need to try and educate them as to what controls to use.

Example

A bit hard to read but hopefully should give you an idea of what your end structure should look like. I have removed a lot of the positioning attributes etc. to try and make it easier to read.

<h3 id="tree_lbl">
  Decision Tree
</h3>
<ul role="tree" aria-labelledby="tree_lbl">
  <li role="treeitem" aria-expanded="false">
      <g class="node">
        <foreignObject tabindex="0" focusable="true" class="nodestyle">Is this a decision tree?</foreignObject>
      </g>
    <ul role="group">
      <li role="treeitem" aria-expanded="false">
        <g class="node">
          <foreignObject tabindex="0" focusable="true" class="nodestyle">Yes</foreignObject>
        </g>
        <ul role="group">
          <li role="treeitem">
            <g class="node"><foreignObject tabindex="0" focusable="true" class="nodestyle">A</foreignObject></g>
          </li>
          <li role="treeitem">
            <g class="node">
              <foreignObject tabindex="0" focusable="true" class="nodestyle">B</foreignObject>
            </g>
          </li>
        </ul>
      </li>
      <li role="treeitem" aria-expanded="false">
        <span>
          <g class="node">
              <foreignObject tabindex="0" focusable="true" class="nodestyle">No</foreignObject></g>
        </span>
        <ul role="group">
          <li role="treeitem" class="doc">
            <g class="node">
              <foreignObject tabindex="0" focusable="true" class="nodestyle">A1</foreignObject>
            </g>
          </li>
          <li role="treeitem" class="doc">
            <g class="node">
              <foreignObject tabindex="0" focusable="true" class="nodestyle">B1</foreignObject>
            </g>
          </li>
        </ul>
      </li>
    </ul>
  </li>
  </ul>
Community
  • 1
  • 1
GrahamTheDev
  • 22,724
  • 2
  • 32
  • 64