Visually-Hidden (sr-only) Utility
Hide text from the screen while keeping it readable by screen readers — for icon buttons, extra link context and live messages.
Live preview Open in Playground
/*
Hide something visually but keep it available to screen readers.
The :not(:focus):not(:active) part lets focusable content
(like a skip link) become visible when it receives focus.
*/
.visually-hidden:not(:focus):not(:active) {
clip: rect(0 0 0 0);
clip-path: inset(50%);
height: 1px;
width: 1px;
overflow: hidden;
position: absolute;
white-space: nowrap;
}Sometimes a sighted user gets context from the layout — an icon, a position on the page — that a screen reader user doesn't. This class adds text only for assistive technology.
- display: none / hidden
- Removes the element from the accessibility tree too. Screen readers won't read it — not what we want here.
- visibility: hidden
- Also hidden from screen readers, and it still takes up space.
- .visually-hidden
- Shrinks the element to 1×1px, clips everything inside, and takes it out of the layout with
position: absolute. It's invisible but still in the accessibility tree.
Line by line
clip-path: inset(50%)clips the box down to nothing. The olderclip: rect(0 0 0 0)is kept as a fallback (it only works withposition: absolute).white-space: nowrapstops the text wrapping into a tall column of single words, which some screen readers would read with odd pauses.- We avoid
margin: -1pxand similar hacks from older versions — they're not needed withclip-path.
For a single icon button, aria-label="Close" is an alternative. Visually-hidden text has one advantage: browser translation tools translate it, while some don't translate aria-label.
Usage
<!-- Icon-only button -->
<button type="button">
<svg aria-hidden="true" focusable="false" width="20" height="20">…</svg>
<span class="visually-hidden">Close menu</span>
</button>
<!-- Make repeated "Read more" links unique -->
<a href="/blog/box-model">
Read more<span class="visually-hidden"> about the box model</span>
</a>