Icon-Only Buttons
Accessible icon-only buttons with visually hidden text labels that provide context for screen reader users while maintaining a clean visual design.
HTML
<button type="button" class="ads-icon-button">
<svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20">
<circle cx="10" cy="10" r="8" stroke="currentColor" stroke-width="2"/>
</svg>
<span class="ads-visually-hidden">User account</span>
</button>
<button type="button" class="ads-icon-button">
<svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20">
<path d="M10 2L12.4 7.3..." fill="currentColor"/>
</svg>
<span class="ads-visually-hidden">Notifications</span>
<span class="ads-badge">3</span>
</button>
CSS
/* Icon-only button */
/* IMPORTANT: Use explicit borders for high contrast mode support */
.ads-icon-button {
display: inline-flex;
align-items: center;
justify-content: center;
width: 44px;
height: 44px;
background-color: var(--ads-primary-color);
color: white;
border: 2px solid var(--ads-primary-color); /* Same as background */
border-radius: 4px;
cursor: pointer;
position: relative;
}
.ads-icon-button:hover {
background-color: var(--ads-primary-hover);
border-color: var(--ads-primary-hover);
}
.ads-icon-button:focus {
outline: 3px solid var(--ads-focus-outline);
outline-offset: 2px;
}
/* Visually hidden text for screen readers */
.ads-visually-hidden {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border-width: 0;
}
/* Notification badge */
.ads-badge {
position: absolute;
top: -4px;
right: -4px;
background-color: var(--ads-error-color);
color: white;
border-radius: 50%;
width: 20px;
height: 20px;
display: flex;
align-items: center;
justify-content: center;
font-size: 12px;
font-weight: 600;
}
Accessibility Guidelines
Key Requirements
- Always include visually hidden text: Required for screen reader users to understand button purpose
- Use aria-hidden="true" on icons: Prevents screen readers from announcing decorative graphics
- Descriptive labels: "User account" and "Notifications" are more helpful than "User" or "Bell icon"
- Minimum touch target: 44x44px ensures easy activation on touch devices
- Clear visual affordance: Button should look clickable with adequate contrast
- Explicit borders: Use border: 2px solid (matching background color) instead of border: none to ensure visibility in Windows High Contrast Mode
Custom Implementation Notes
When to use icon-only buttons: Reserve icon-only buttons for universally recognized actions (like close, search, menu) in contexts where space is limited, such as mobile interfaces or toolbars. For primary actions or less common functions, always prefer buttons with visible text labels.
Tooltips as supplements: While tooltips can help sighted users understand icon buttons, they are not a replacement for accessible labels. Many users cannot hover (touch devices, keyboard users) and screen readers need the text in the DOM, not in tooltip attributes.
The ads-visually-hidden class: This CSS technique hides text visually but keeps it in the accessibility tree. Never use display:none or visibility:hidden for accessible labels as these hide content from assistive technology.
How to Test for Accessibility
-
Screen Reader Test:
- Enable NVDA, JAWS, or VoiceOver
- Navigate to the button with Tab
- Verify it announces: "User account, button" or "Notifications, button"
- Verify the icon itself is NOT announced
- For notification badge, verify count is announced
-
Keyboard Navigation:
- Tab to each icon button
- Verify 3px blue focus indicator is clearly visible
- Press Enter or Space to activate
- Verify activation works correctly
-
Visual Test:
- Verify button is exactly 44x44px
- Check icon color contrast against background (4.5:1 minimum)
- Verify focus indicator is visible and meets contrast requirements
-
Browser Dev Tools:
- Inspect Accessibility tree
- Verify accessible name is the visually hidden text
- Verify SVG has aria-hidden="true"
- Check that visually hidden span is not displayed but is in DOM
References
- WCAG 2.2 Success Criterion 1.1.1: Non-text Content (Level A)
- WCAG 2.2 Success Criterion 4.1.2: Name, Role, Value (Level A)
- WCAG 2.2 Success Criterion 2.4.7: Focus Visible (Level AA)
- WCAG 2.2 Success Criterion 2.5.8: Target Size (Minimum) (Level AA)
- WCAG 2.2 Success Criterion 2.5.3: Label in Name (Level A)