Aria-Labels & Graphs

Recently, I was tasked with making a bar graph presentation more accessible to users who employ screen readers without changing the desired affects for visual users. The goal was to rely to a user's screen reader the graph's information in the form of a sentence. This would paint a mental picture of the graph's result. Here's a sampling of what the HTML code looked like initially:

<div class="inner-container sharing">
  <h5>All Shared</h5>
  <div data-graph-1 class="graph active" style="width: 4.285714285714286%;"></div>
  <div data-graph-label-1 data-dynamic-text class="graph-label bold" data-aria-label-template="share all expenses">5% of couples like you
  </div>
</div>

Possible Solution 1

At this point I thought there's no need to show the graphical bar graph so that can be hidden with aria-hidden. Also, I was given direction to make it read just the sentence describing the bar graph. With that, I hid all the surrounding elements with aria-hidden except the text string that I want the screen reader to read. Lastly, in order to override what was announced I added an aria-label with the sentence I wanted read. Here's the code for that:

<div class="inner-container sharing">
  <h5 aria-hidden="true">All Shared</h5>
  <div data-graph-1 class="graph active" aria-hidden="true" style="width: 4.285714285714286%;"></div>
  <div data-graph-label-1 data-dynamic-text class="graph-label bold" data-aria-label-template="share all expenses" aria-label="Like you, 5% of couples share all expenses">5% of couples like you
  </div>
</div>

That turned out to be a fail for a few reasons:

  1. The headings should never be hidden. Some people use their screen reader to navigate to them directly. This would make them hard to reach.
  2. When I tested it in Safari/Mac Voiceover, the heading was still being spoken.
  3. The aria-label was read but the role of the div was announced as group. This posed a problem because it miscommunicated the intention of the text string and allowed the user to interact with the aria-label and the text inside the div.
  4. Aria-labels, like bandages, only cover what's there.

Possible Solution 2

After thorough review, I asked for help and received some sage advice. First restore visibility to the heading and then visually hide the parts of the string that I don't want visual users to see but reveal that content to the screen reader users. The html is being manipulated by javascript so while the concept is simple, editting the loop that produces is the html is the main roadblock to success. So I ended up thinking through was taking the base string 5% of couples like you and crafting it to say something a little different visually. This lead me to experiment with sprinkling in so aria-hidden attributes and visuallyHidden classes.

So here's the section version:

HTML

<div class="inner-container sharing">
  <h5>All Shared</h5>
  <div data-graph-1 class="graph active" aria-hidden="true" style="width: 4.285714285714286%;"></div>
  <div data-graph-label-1 data-dynamic-text class="graph-label bold" data-aria-label-template="share all expenses"><span class="visuallyHidden">Like you, </span>5% of couples <span class="visuallHidden">share all expenses</span><span aria-hidden="true"> like you</span>
  </div>
</div>

CSS

.visuallyHidden {
  position: absolute !important;
  margin: -1px;
  padding: 0;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: polygon(0 0 0 0);
}

Visually this reads as:

5% of couples, like you

A screen reader announces this:

Like you, 5% of couples share all expenses

Success!!

This renders out the text as I needed it to be expressed visually and through a screen reader. And because it's one long string, it doesn't announce as a group. Using the visuallyHidden class, I am hiding the text I don't want visual users to see in a 1px by 1px box that is large enough to be picked up by a screen reader. display: none would have hidden the text to both visual users and screen readers. opacity: 0 or visibility: hidden would have thrown off the way I wanted the end result to be styled. Also, the focus indicator would surround a suspicious looking empty area to the right of the text. I added in the data-aria-label-template attribute to help with constructing the string.

As with any puzzle, there's more than one way to solve this. Hopefully this solution saves you some time and heartache.

Testing Environments

I tested this with: