Optimizing screenreader accessibility for icon-only buttons

Aron Schüler Published
Updated on


Buttons consisting only of an icon are a common design pattern throughout most websites. But what if the user is depending on a screenreader? You cannot change the design by just adding a text but having no text at all denies any accessibility. Well, there is a simple fix!

Using a <span> next to your icon

The solution is really simple: We insert a text anyway, describing what the button does, but hide it so that it does not conflict with the design.

So, instead of writing a button with a svg like this (svg taken from Material Design Icons):

<button>
  <svg style="width:24px;height:24px" viewBox="0 0 24 24">
    <path
      fill="currentColor"
      d="M17,13H13V17H11V13H7V11H11V7H13V11H17M19,3H5C3.89,3 3,3.89 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V5C21,3.89 20.1,3 19,3Z"
    />
  </svg>
</button>

We add a span and style it with the class sr-only (which is already defined if you use tailwind and does the same!):

<button>
  <svg style="width:24px;height:24px" viewBox="0 0 24 24">
    <path
      fill="currentColor"
      d="M17,13H13V17H11V13H7V11H11V7H13V11H17M19,3H5C3.89,3 3,3.89 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V5C21,3.89 20.1,3 19,3Z"
    />
  </svg>
  <span class="sr-only"> Add a new item </span>
</button>

and style the sr-only class like this:

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

Adding title and aria-labeledby to increase accessibility

Another additional way of increasing the accessibility would be to add the title and aria-labeledby attributes to the button. These also provide a tooltip on hover, so users that don’t understand the direct purpose of your icon-only button can actually understand what the intention was.

To do so, I extended the button from above like this:

<button aria-labelledby="add-button-text" title="Add a new device">
  <svg style="width: 24px; height: 24px;" viewBox="0 0 24 24">
    <path
      fill="currentColor"
      d="M17,13H13V17H11V13H7V11H11V7H13V11H17M19,3H5C3.89,3 3,3.89 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V5C21,3.89 20.1,3 19,3Z"
    />
  </svg>
  <span id="add-buton-text" class="sr-only">Add a new device</span>
</button>

Done!

Now, we can be sure that no one has problems accessing our still stylish buttons.

A complete example would look like this:

{{< codesandbox broken-night-k7erhz >}}


Related Posts

Find posts on similar topics:


Support me via buymeacoffee

If I helped you solve a problem or you just like my content, consider supporting me by buying me a coffee.

Buy me a coffee

Comments