Visually hidden text, aria-label, and the title attribute compared head to head, with practical examples from Hyva
A cart icon, a magnifying glass for search, or a plain icon for social share buttons looks self-explanatory to sighted users, but to a screen reader such a button without extra markup is simply a nameless button element. This article compares the three common patterns, visually hidden text, aria-label, and the title attribute, on solid technical grounds, and shows using cart, search, and social share icons in Hyva which pattern actually works reliably and when.
Table of Contents
- 1. The problem: icon-only buttons without visible text
- 2. The visually hidden text pattern: the most robust solution
- 3. aria-label: pros and cons per screen reader
- 4. The title attribute: why it isn't a reliable solution
- 5. Tooltip compatibility: pairing a visible tooltip with a programmatic name
- 6. Practical example: the cart icon in Hyva
- 7. Practical example: the search icon in the header
- 8. Practical example: social share icons
- 9. Decision guide: which pattern when
- 10. Summary
- 11. FAQ
1. The problem: icon-only buttons without visible text
A button consisting purely of an SVG icon, say a cart symbol or a magnifying glass, has no accessible name by default from the accessibility tree's point of view, unless the icon itself carries an embedded, visible text element. A screen reader then announces such a button merely as a button, with no information whatsoever about what function is hiding behind it, which effectively turns operation into guesswork for blind users.
The problem sits purely at the programmatic level, not the visual one: sighted users usually recognize the meaning of a cart icon reliably, since it's a largely standardized visual convention. But that implicit, purely visual convention doesn't automatically carry over into a programmatically accessible name, which is why an explicit text alternative needs to be added technically.
2. The visually hidden text pattern: the most robust solution
The visually hidden text pattern places real, actual text in the DOM but hides it purely visually via a CSS class that removes the text from the layout without deleting it from the accessibility tree. Unlike display none or visibility hidden, which also make an element invisible to screen readers, text hidden through off-screen positioning stays fully readable.
The decisive advantage of this pattern over aria-label is that the text exists as real, DOM-present content and thus also gets picked up by tooling that doesn't reliably process pure ARIA attribute content, say certain translation tools, browser extensions, or older screen reader versions. The text can also be made visible again on demand via JavaScript or CSS, say at a responsive breakpoint where there's enough room for visible text.
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
3. aria-label: pros and cons per screen reader
aria-label sets an element's accessible name directly as an attribute value, with no additional DOM-visible text needed, which makes the pattern especially compact and simple to apply. In practice, aria-label is reliably supported by all relevant screen readers, NVDA, JAWS, and VoiceOver, making it technically equivalent to the visually hidden text pattern for pure read-out purposes.
The practical downside of aria-label shows up with tooling that doesn't hook into the accessibility API but reads visible or DOM-present text directly instead, say browser translation features, in-browser text search via Ctrl-F, or certain test automation tools that primarily target visible text rather than ARIA attributes. An aria-label is also easy to forget updating when a button's function changes, since it leaves no visible trace in the markup that would jump out during a code review.
4. The title attribute: why it isn't a reliable solution
Many developers mistakenly use the title attribute as a simple text alternative for icon buttons, since it additionally produces a visual tooltip on mouse hover. In reality, though, screen reader support for title as an accessible name is inconsistent: some browser and screen reader combinations read title out, others ignore it entirely, especially once an aria-label or visible text is also present, which then takes precedence.
A further practical problem concerns keyboard and touch users: a title tooltip only appears on mouse hover, meaning it's fundamentally unreachable for pure keyboard users and for touch devices without hover capability, regardless of screen reader support. The title attribute should therefore be understood at most as visual supplementary information for mouse users, never as the sole, reliable text alternative for the accessible name.
5. Tooltip compatibility: pairing a visible tooltip with a programmatic name
For icon buttons meant to give both a sighted mouse user and a screen reader user the same information, the recommended combination is a custom, JavaScript-driven tooltip element paired with the visually hidden text pattern, rather than relying on the unreliable title attribute. The tooltip delivers the visible information on hover or focus, while the button's accessible name stays fixed independently via the hidden text.
It's important to make the tooltip appear on keyboard focus as well, not just mouse hover, so sighted keyboard users, say people with motor impairments, get the same visual information as mouse users. Such a tooltip should also be wired up via role tooltip and an aria-describedby link, not via aria-label, since aria-label would otherwise overwrite or duplicate the hidden text already present.
6. Practical example: the cart icon in Hyva
In a Hyva theme, the cart button in the header usually consists of an SVG icon plus a dynamically updated item-count badge. The accessible name needs to reflect both the base function, open cart, and the dynamic item count, since otherwise a plain icon text won't update after a product gets added, and screen reader users end up hearing a stale number.
The most robust implementation combines a visually hidden base text with a reactively updated, likewise hidden count text driven by Alpine.js, so the entire accessible name gets read out correctly on every cart change automatically, without needing a separate aria-live update, since the name gets re-read anyway the next time the button receives focus.
<button
type="button"
class="relative"
x-data="{ count: 3 }"
aria-label="Open cart"
>
<svg class="w-6 h-6" aria-hidden="true"><!-- icon path --></svg>
<span
class="sr-only"
x-text="count + ' items in cart'"
></span>
<span
class="absolute -top-1 -right-1 bg-red-600 text-white text-xs rounded-full px-1.5"
aria-hidden="true"
x-text="count"
></span>
</button>
7. Practical example: the search icon in the header
The magnifying glass icon in the header carries a dual function in many Hyva themes: in the closed state it opens the search field, in the open state the very same button closes the search again. A static aria-label like open search becomes semantically wrong after the first click in this case, since the button then actually closes rather than opens, even though the label stays unchanged.
The correct solution binds the aria-label reactively to the open state, so it delivers either open search or close search depending on the state, combined with aria-expanded, which additionally communicates the current state structurally to assistive technology, independent of the label's pure text content.
<button
type="button"
x-data="{ open: false }"
x-on:click="open = !open"
:aria-label="open ? 'Close search' : 'Open search'"
:aria-expanded="open"
>
<svg class="w-6 h-6" aria-hidden="true"><!-- magnifier or X icon --></svg>
</button>
8. Practical example: social share icons
For a row of social share icons, say for Facebook, X, and Pinterest, the same basic problem repeats several times in a row: every icon needs to name both the channel and the action in its accessible name, say share on Facebook rather than just Facebook, since the plain brand name without an action verb doesn't provide enough information about the button's actual function.
For a group of related share buttons, an enclosing nav with a fitting aria-label like share on social networks should also bundle the individual buttons semantically, so screen reader users recognize the group as a coherent section instead of hearing five individual, context-free buttons read out one after another.
9. Decision guide: which pattern when
For static icon buttons with no dynamic content, visually hidden text and aria-label are technically nearly equivalent, though visually hidden text remains the more robust default choice because of its better compatibility with tooling outside the pure accessibility API. Visually hidden text also suits dynamic content like the cart counter particularly well, since it can be updated with the same reactivity mechanisms as the rest of the Alpine.js component.
aria-label remains a sensible choice when the accessible name can be derived simply and purely reactively from a state, as with the search icon's two states of open and closed, while the title attribute isn't advisable as the sole solution in any of the cases described here, and should at most be added as a supplementary visual tooltip for mouse users. The table below summarizes support for the three patterns across common screen readers.
| Pattern | NVDA | JAWS | VoiceOver |
|---|---|---|---|
| Visually hidden text | Reliably supported | Reliably supported | Reliably supported |
| aria-label | Reliably supported | Reliably supported | Reliably supported |
| title attribute | Inconsistent, often ignored | Inconsistent, often ignored | Usually not read out |
| No text pattern | Announces only button | Announces only button | Announces only button |
Mironsoft
WCAG audits, accessible Magento shops, and training
Not sure whether the shop is actually accessible?
We audit existing Magento shops against WCAG 2.2, fix concrete barriers in the Hyvä frontend, and train teams so accessibility stays anchored in the development process for good.
WCAG Audit
Systematically review the shop against WCAG 2.2 AA, with a prioritized issue list.
Fixing Barriers
Concrete implementation: keyboard operability, screen reader support, contrast, forms.
Team Training
Raise developer and editor awareness for accessible implementation day to day.
10. Summary
Text Alternatives for Icon Buttons: The Essentials at a Glance
Core problem
An icon-only button has no accessible name for screen readers without extra work.
Most robust choice
Visually hidden text, since it stays real DOM content and is more broadly compatible than aria-label.
Unreliable
The title attribute is handled inconsistently by screen readers and is unreachable for touch.
Dynamic buttons
State-dependent buttons like search need a reactive aria-label plus aria-expanded.