Accessible icon buttons with SVG icons
By Colton Griffith · Updated
Icons make interfaces compact, but an icon on its own tells a screen reader nothing, and a tiny icon is hard to tap. Accessibility problems with icons come down to four things, and each has a small, reliable fix.
1. Decide: decorative or meaningful?
Every icon is one or the other.
- Decorative: the icon repeats information that's already in visible text. For example, a trash icon next to the word "Delete". Screen readers should skip it.
- Meaningful: the icon is the only way the information is shown. For example, an icon-only button, or a warning icon with no text. Screen readers need a text alternative.
2. Hide decorative icons
For inline SVG, add aria-hidden="true":
<button type="button">
<svg aria-hidden="true" focusable="false" …>…</svg>
Delete
</button>
focusable="false" stops older versions of Internet Explorer and legacy Edge from putting the SVG in the tab order. It's harmless to keep.
For <img>, use an empty alt:
<img src="/icons/ic_fluent_delete_24_regular.svg" alt="">
An empty alt is not the same as a missing one. Without alt, some screen readers read out the file name, "ic fluent delete 24 regular", which is worse than nothing.
3. Label icon-only controls
Put the accessible name on the interactive element, not the icon:
<button type="button" aria-label="Delete file">
<svg aria-hidden="true" focusable="false" …>…</svg>
</button>
Guidelines for good labels:
- Describe the action, not the picture. "Delete file", not "Trash can".
- Be specific when there are several. On a list of files, "Delete report.pdf" is clearer than five buttons all called "Delete".
- Match any tooltip. If you show a tooltip, its text should match the label, so sighted and non-sighted users hear the same name.
For toggle buttons, add state:
<button type="button" aria-label="Favorite" aria-pressed="true">…</button>
Screen readers announce "Favorite, toggle button, pressed". The filled/regular icon swap covers the visual side. See filled vs. regular icons.
4. Make targets big enough
A 24 px icon is a comfortable size to see, but a small target to tap. WCAG 2.2 sets a minimum target size of 24 × 24 CSS pixels, with some exceptions. Many design systems aim for 40–48 px on touch devices. You don't need a bigger icon, just more padding:
.icon-button {
display: inline-grid;
place-items: center;
min-width: 44px;
min-height: 44px;
padding: 10px;
}
5. Check contrast
Icons that convey meaning need enough contrast against their background. WCAG asks for at least 3:1 for graphical objects needed to understand the content. The default Fluent gray, #212121, easily passes on white. Light grays often don't: #a0a0a0 on white is below 3:1. If you use currentColor, the icon inherits the text color, and text colors are usually chosen with contrast in mind already.
6. Don't forget focus styles
Icon buttons need a visible focus indicator, just like text buttons. Avoid outline: none unless you replace it:
.icon-button:focus-visible {
outline: 2px solid #0f6cbd;
outline-offset: 2px;
}
Quick checklist
- Decorative icons have
aria-hidden="true"oralt="" - Icon-only buttons and links have an
aria-labelthat describes the action - Toggles use
aria-pressed(oraria-currentfor navigation) - Targets are at least 24 × 24 px, ideally 44 px on touch
- Meaningful icons have 3:1 contrast or better
- Focus is clearly visible
Find the icons mentioned here with the icon search, or read another guide.