Icon Button Label
Status: ready
Intent
An icon button has a task name that the user can hear, say and understand.
Problem
An icon isn't a name. An asset name isn't user language. An SF Symbol name isn't product copy. A button called xmark isn't a button called "Close".
Solution
Verdict: visible text when there's room. Otherwise a localized accessibilityLabel that names the action or the destination, not the shape. When the icon repeats, the label names the object.
Why: the label is what VoiceOver reads, what Voice Control matches and what support says on the phone. A shape name helps none of them.
| Good | Bad |
|---|---|
| Close | X icon |
| Share receipt | square and arrow up |
| Filter results | filterButton |
| Add jasmine tea to favorites | Favorite (×10 in a list) |
Implementation
SwiftUI, icon only:
Button {
openFilters()
} label: {
Image(systemName: "slider.horizontal.3")
}
.accessibilityLabel("Filter results")
SwiftUI, visible text. The visible text is the name, no extra label:
Button {
openFilters()
} label: {
Label("Filter results", systemImage: "slider.horizontal.3")
}
Label with .labelStyle(.iconOnly) keeps the text as the accessible name and shows only the icon. That's the simplest icon-only button with a name.
UIKit:
filterButton.accessibilityLabel = "Filter results"
shareButton.accessibilityLabel = "Share receipt"
closeButton.accessibilityLabel = "Close"
A repeated icon names its object. For a favorite button the action is on/off, so it's a toggle with a stable name:
Toggle(isOn: $tea.isFavorite) {
Label("Favorite \(tea.name)", systemImage: tea.isFavorite ? "heart.fill" : "heart")
}
.toggleStyle(.button)
.labelStyle(.iconOnly)
When the visible text and the label differ, the visible text stays a valid Voice Control command:
addToCartButton.accessibilityLabel = "Add jasmine tea to cart"
addToCartButton.accessibilityUserInputLabels = ["Add to cart", "Add jasmine tea"]
Check
Profile: VoiceOver
Task: swipe through the toolbar and one list
Expected: every icon button has a task name
no asset or symbol names
repeated icons name their object
Profile: Voice Control
Task: activate each icon button by name
Expected: each command works
repeated controls can be told apart
Profile: another language (for example German)
Task: the same screen
Expected: labels are translated, no English or identifiers leak through
Pitfalls
- Not by shape: "slider icon".
- Not by implementation:
filterButton. - No role in the label: "Filter button".
- No identical labels on 10 favorite buttons.
- No
accessibilityIdentifieras a label. - No label that contradicts the visible text.
WCAG mapping
4.1.2 Name, Role, Value: the button has a name and a role.1.1.1 Non-text Content: the icon has a text alternative.2.5.3 Label in Name: the accessible name contains the visible text.2.4.6 Headings and Labels: the label describes the purpose.