Truncated Text and Screen Readers: An Accessibility Deep Dive
Clipping text is a classic CSS challenge that keeps returning to the conversation. We've covered single-line ellipsis, multi-line clamping, and the tricky interplay between flexbox and truncated text. Those techniques solve a visual problem, but there's an accessibility dimension that often gets shortchanged: what happens when the text is clipped for sighted users and a screen reader user needs access to the full content?
A recent experiment took on that exact scenario. The premise: build an expandable panel using the newer (Chrome-only) technique for transitioning an element from zero to an auto height. The panel contains a button to trigger the expansion. A screen reader already announces the full text inside the collapsed panel, so the button is unnecessary for assistive tech users. Yet, if we just drop a disabled attribute on it, we create a confusing situation where the button appears non-functional without explanation. It's a case where the "don't hide controls" rule and the "don't duplicate announcements" rule collide.
The Button Problem
The first instinct is to hide the button from screen readers entirely. But aria-hidden="true" on a focusable element is not a best practice. The button remains focusable and operable by keyboard, yet is invisible to the accessibility tree — a clear anti-pattern.
The next option is the ARIA equivalent of disabled: aria-disabled="true". This hides the button's functionality from assistive tech without making it visually inert. The button is still there, still looks enabled, but a screen reader will announce it as disabled. That answers "can I press it?" but leaves open "why can't I?" — a gap that needs filling.
Describing the Button Accessibly
ARIA offers two natural paths for adding context to an interactive element like this button:
aria-label: Composes a custom accessible name for the button, overriding whatever text it contains.aria-labelledbyworks similarly but references a visible element byidinstead.aria-describedby: References another element to provide an accessible description alongside the name.
The descriptive route seems more semantically precise. We want to explain why the button is disabled to screen reader users while keeping the wait for visual users clean. That means introducing a hidden span purely as a target for aria-describedby. A classic .visually-hidden utility removes it from visual flow while leaving it available to the accessibility tree.
The full text is already available to screen readers.
With basic styling on the .visually-hidden class — absolute positioning, clip, and size values that keep the element out of layout but in the accessibility API — VoiceOver picks up the button, reads the context, and leaves the disabled state clear.
That works, but the markup is weighty: a bespoke hidden element created solely for the description. The aria-label approach avoids that by putting the context directly on the button:
Testing in VoiceOver reads the label content smoothly, announcing the button and its state only once. For a self-taught accessibility journey, this looks like a shippable solution.
The Catch with aria-label
A closer inspection of the button's accessibility API reveals a subtle mismatch. The button's accessible name comes from the aria-label, which is accurate. But two other ARIA attributes exist specifically for describing rather than naming elements:
aria-description: Intended to annotate the current element directly. It is still in the Editor's Draft of the ARIA 1.3 specification, though broadly supported in Caniuse. It's likely safe, but shipping a feature that hasn't reached formal recommendation status invites second guesses.aria-describedby: The more widely supported way to add that description through a reference to another element.
The devil is in the data modeling. The accessibility tree treats the aria-label text as the button's name, not its description. That means the context we're adding is getting attached in the wrong slot. For most users, the distinction is invisible, but for assistive tech it matters — the name and description are announced in different order and served to different queries.
There is also the larger question of whether an expandable, truncated text excerpt is worth this complexity at all. Hiding content is generally a bad default. If the full text is available to screen readers and the expand mechanism only serves sighted users, maybe the clipped state itself is the anti-pattern. The comment section will likely sort that out, but as a learning exercise, this demonstrates just how many moving parts sit between a simple "show more" button and a truly accessible interface.



