I have a icon which is not decorative, and it is not directly within an interactive element, though there is an interactive element in the hierarchy.
Something like this:
<button type="button">
<div> Some info </div>
<div> other info </div>
<i class="material-icons"> icon </i>
</button>
This icon displays information about the status of this item.
To make it more accessible, is it better to change the structure to this:
<button type="button">
<div> Some info </div>
<div> other info </div>
<span aria-label="the actual status">/
<i class="material-icons"> icon </i>
</span>
</button>
OR this:
<button type="button">
<div> Some info </div>
<div> other info </div>
<i class="material-icons"> icon </i>
<span class="sr-only"> the actual status </span>
</button>
I have a icon which is...not directly within an interactive element
That's not what your code example shows.
<button>
<i>
</button>
Your icon is definitely contained within an interactive element. When a screen reader user tabs to the button, all the text contained between the <button> element will be read as the name of the button. So you'll hear "some info other info icon, button".
You could put an aria-label
on the button but I don't like to do that because it duplicates text.
<button type="button" aria-label="some info other info actual status">
<div> Some info </div>
<div> other info </div>
<i class="material-icons"> icon </i>
</button>
If you happen to change <div>other info</div>
to <div>some other info</div>
, you'd have to remember to change the aria-label
to match.
Your suggestion to put an aria-label
on the <span>
might feel like the right thing to do but you can't stick an aria-label
on just any element (although aria-label
is a global attribute) because the element needs a "role" as well. See "Practical Support: aria-label, aria-labelledby and aria-describedby".
So your last solution is typically how icon fonts are handled, provided you also "hide" the icon from the screen reader with aria-hidden="true"
.
<button type="button">
<div> Some info </div>
<div> other info </div>
<i class="material-icons" aria-hidden="true"> icon </i>
<span class="sr-only"> the actual status </span>
</button>