Prototypr

Prototyping, UX Design, Front-end Development and Beyond 👾 | ✍️ Write for us https://bit.ly/apply-prototypr

Follow publication

Accessible components: #2 dynamic ARIA labels

With an input component we can set up a dynamic label fairly easily whether that’s text or creating both a dynamic ‘id’ and <label> in the code behind.

Taking a tooltip/popover component as an example which only displays a clickable icon, we can end up with an accessibility error of ‘empty button’ as the icon won’t provide any information to the screen reader.

In the below examples I’ll be discussing ‘aria-label’ and ‘aria-labelledby’, if you haven’t explored these before you may find the below links useful:

Please note I’m using basic angular in the below examples, but the same principle can be applied across various frameworks.

How can we fix this?

Example One:

Popover component code:

<button type="button" role="button" id="{{popover.id}}" aria-label="display popover" class="random-popover-icon" (click)="openPopover =! openPopover">  <div *ngIf="openPopover" class="popover-content">
<span>Random popover example</span>
</div>
</button>

The ‘aria-label’ attribute applies a label for a screen reader, however even if you don’t have multiple popovers on the page this won’t really tell the user much about the popover they’re trying to display. For example which section does this relate to?

Verdict: It’s a pass but still not very informative to the user.

Example Two:

We could try the ‘sr-only’ class, which has become a common fix which looks like the below:

<button type="button" role="button" id="{{popover.id}}" class="random-popover-icon" (click)="openPopover =! openPopover"><span class="sr-only">Display {{popover.title}} popover</span><div *ngIf="openPopover" class="popover-content">
<span>Random popover example</span>
</div>
</button>

In this example we added a span with a class of ‘sr-only’. This however is just adding duplicated mark-up and with the availability of ‘aria’ controls this does seem a little unnecessary.

‘sr-only’ stands for screen readers only, which is a commonly used class to display an item of markup to screen readers only (originated from bootstrap). With the below css:

.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0,0,0,0);
border: 0;
}

Verdict: Again it’s a pass but unnecessary.

Example Three:

Alternatively we could use the below dynamic example:

<button type="button" role="button" id="{{popover.id}}" attr.aria-label="display {{popover.title}} popover" class="random-popover-icon" (click)="openPopover =! openPopover"><div *ngIf="openPopover" class="popover-content">
<span>Random popover example</span>
</div>
</button>

This example is much better. By adding ‘attr.’ to our ‘aria-label’ we can now make this dynamic on the button itself. In simple terms ‘attr’ makes this attribute dynamic. If you don’t use the ‘attr.’ attribute this won’t work.

Verdict: A pass and it’s semantic. By using the aria control ‘attr.aria-label’ we have made this label dynamic.

aria-labelledby

Although the above is using ‘aria-label’ as the example, the same can be applied to ‘aria-labelledby’.

Let’s look at an example of how this would work. Lets say we wanted to make a menu component just for example (example 7 from the mozilla aria examples page):

Menu component code:

<div role="menubar">
<div role="menuitem" id="fileMenu">File</div>
<div role="menu" aria-labelledby="fileMenu">
<div role="menuitem">Open</div>
<div role="menuitem">Save</div>
<div role="menuitem">Save as ...</div>
</div>
</div>

Let’s imagine we’ve now made this a re-usable component. We could also make that aria-labelledby easier to re-use multiple times in one page per the below:

<div role="menubar">
<div role="menuitem" id="menuList">{{menu.name}}</div>
<div role="menu" aria-labelledby="menuList">
<div role="menuitem" *ngFor="#menu of menus">{{menu.item}}</div>
</div>
</div>

With attr.aria-labelledby:

<div role="menubar">
<div role="menuitem" id="{{menu.id}}">{{menu.name}}</div>
<div role="menu" attr.aria-labelledby="{{menu.id}}">
<div role="menuitem" *ngFor="#menu of menus">{{menu.item}}</div>
</div>
</div>
<!-- The implementation of our component-->
<menu-component id="foodItemsMenu" [service]="randomService.foodItems"></menu-component>

This now means, which ever ID we pass into the component like the above ‘foodItemsMenu’ will be used in the ‘aria-labelled’ attribute, making this more accessible for any of our users.

If you found this useful and would like to see any of the other ‘accessible components’ series articles you can find them here:

Thanks

If you liked this post, please hit both the follow and clap buttons below. You can also follow me on twitter to keep up to date with future posts.

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

Published in Prototypr

Prototyping, UX Design, Front-end Development and Beyond 👾 | ✍️ Write for us https://bit.ly/apply-prototypr

Written by Paul Champion

Developer and Designer from Southampton, UK. Passionate about UX, CSS, Accessibility and coffee.

No responses yet

Write a response