Making Accessible Icon Buttons

— 4 minute read


So many icons have an ingrained meaning to us that when we use one on a button the action that will be triggered is second nature. This is great for decluttering our interfaces as we can omit lots of lengthy text descriptions from the buttons.

You will probably be familiar with this approach to add an icon using the Font Awesome library:

<button>
<i class="fa fa-refresh fa-2x"></i>
</button>

To sighted users this button appears as below with the fairly clear action that it will refresh some part of the interface.

A button with a refresh icon on it

The problem with this approach comes when screenreaders try to interpret these icons. In our example above we use an icon font to display these icons which screenreaders won't read aloud in the way you would want. They will likely read out a machine representation of the icon or if used in a pseudo element (like in our example), omit it completely. Meaning your button will just be read as "button". It's anyone's guess what will happen if it is pressed!

The VoiceOver caption interface showing the word 'button'

To make these buttons accessible we have to give screenreaders something to read out and not rely on it interpreting our icon which might not follow the usual meaning anyway (e.g. the classic 'retweet' icon could be used as a 'refresh' icon). We do this by ensuring that the icon is ignored by assistive technology to avoid it causing confusion, and then adding text that only screenreaders can see.

To 'hide' the icon itself from assistive technology we simply add aria-hidden="true" to the icon's element.

<button>
<i class="fa fa-refresh fa-2x" aria-hidden="true"></i>
</button>

Now we add the button description text that the assistive technology will read aloud. We first need to add a special CSS style that will hide text from showing on screen but keep it available to screenreaders. We can't use the typically methods of display: none or visibility: hidden as these would also hide it from screenreaders.

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

We now add a span inside our button with our descriptive text and give it the sr-only (i.e. screenreader only) class.

<button>
<i class="fa fa-refresh fa-2x" aria-hidden="true"></i>
<span class="sr-only">Refresh List</span>
</button>

Now when the screenreader hits our button it will read out the nice description while looking exactly the same as it did before.

The VoiceOver caption interface showing the words 'Refresh List, button'

Boom! Accessible icon buttons - incredibly simple to add and it will help keep your website accessible to all.

Filed under