Quick Summary
A task of making a cool toggle button comes your way and you’re headed down the div lane. What happens next? Sounds like a crime thriller but it could actually be a nightmare for your users. Explore what is the best approach, how to ensure the button is accessible, and what could go wrong when you replace native HTML elements with artificial ones.
Toggle Button
To begin making a toggle button or an icon button with toggle feature, the easiest and straight forward option is to use a div and style it according to the design. Like this button here
We have a like button with a thumbs-up icon similar to what we see under social media posts, clicking it makes it active and clicking it again makes it inactive or reset. Works well visually and functionally. But right now, it has a few things missing.
Trap of Artificial Button
Since we used a div and icon to make a toggle button, it does not have the properties of a native HTML button. Which means we would miss out on these built-in features
Feature | Div | Button | Comment |
---|---|---|---|
Tab indexing | ❌ | ✅ | Using keyboard to navigate |
Button label | ❌ | ❌ | Users have to guess the usage by icon |
Keyboard support | ❌ | ✅ | Spacebar support |
Default focus styles | ❌ | ✅ | |
Semantic | ❌ | ✅ | Browser doesn’t know if it is a button |
Accessibility | ❌ | ⚠️ | Button is inherently more accessible but not totally |
Form features | ❌ | ✅ |
These issues could affect the user experience and they are easily be overlook if not tested specifically. Even if we notice and try to fix them, we would need to manually solve them.
Addressing Accessibility
How do we solve the issues discussed above?
Well, the best solution would be to use a <button>
element. Using button in place of the div will restore the built-in button features. This could affect the styles of the icon button due to the default button styles. All browser default button styles can be removed by using a CSS property all: unset
, but this property removes every default style, including the focus styles which we should still keep. Alternatively we can only update the styles that are affecting our button design, such as background, margin and border.
Using a button, improves the element without any extra work. However, there are still a few more things to address
It is still a generic button element and not a toggle button
It still misses the label
ARIA tags for A11y
Toggle state
Using Labels to Clearly Describe the Button
The purpose of a button must be clear to the user. An icon on its own may not be clear enough or even accessible. Icons are graphics made of lines and shapes, and their interpretation can be highly subjective. They also limit users to understanding the control only visually.
Adding a descriptive label to the button improves accessibility, while showing the label on hover can enhance the overall user experience.
Here’s a list of things to consider for button labelling
Visible text label next to the icon - Ideally, just include a label if there’s no good reason to hide it
Hidden text in the button - Add the text in a span beside the icon and hide it using CSS
Using
aria-label
- Use thearia-label
tag on the button to add a descriptive labelTooltip on hover - Use a tooltip to show the label when the user interacts with the button
Toggle State
Now we have the button more accessible and working fine. But what about the toggle state? Is it accessible to every user yet? Maybe we can see it visually as the design and styles change after it is clicked and we have the state in our JS probably. But how does the browser know in which state the button is currently? So how would users with assistive tech know the state?
This is where the aria-pressed tag comes in to help. It is meant for using as a state indicator for toggle buttons. We can set the current toggle state of the button in this tag like this
<button aria-pressed="true">...</button>
💡Pro-tip: Do not confuse the user by changing the content of the button when toggled. Also mentioned in MDN docs here
Downsides of Not Using Native Button
Replacing any native HTML element comes with its downsides. Native elements are recognised by the browsers and include a lot of important properties that help with a consistent cross-browser behaviour and accessibility.
Although we don’t have a dedicated toggle button in HTML but by using a generic button element with proper labels and pressed state, we can get close to the best possible solution.
TL;DR
A quick checklist for toggle/icon buttons
Basic button features (by browser)
Descriptive button label
Accessibility tags
Toggle state
Top comments (0)