Snippets / Accessibility /

Visually Hidden (Screen Reader Only)

The .sr-only utility hides text from sighted users while keeping it in the accessibility tree — the correct way to label icon buttons, add skip links, and describe badge states.

Icon button — "Delete item" read by screen reader, invisible to mouse users
Online (status: active) Badge with extra context appended
Skip to main content Tab to this area — skip link appears on focus
Widely Supported
a11yno-js

Quick implementation

/* .sr-only — visually hidden but in the accessibility tree */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border-width: 0;
}

/* .sr-only-focusable — hidden until focused (for skip links) */
.sr-only-focusable:not(:focus):not(:focus-within) {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border-width: 0;
}

/* Usage examples:
   Icon button — visible icon, hidden label */
/*  */

/* Skip link — appears on keyboard focus */
/* Skip to main content */

/* Live region for status announcements */
/* 
Item added to cart
*/

Prompt this to your LLM

Includes role, constraints, two framework variants, and edge cases to handle.

You are an accessibility-focused CSS developer. Implement visually-hidden text patterns for a design system.

Requirements:
1. Provide the canonical .sr-only class using position: absolute, width/height: 1px, clip: rect(0,0,0,0), overflow: hidden, white-space: nowrap.
2. Explain why display: none and visibility: hidden are wrong — they remove elements from the accessibility tree entirely.
3. Explain why clip-path: inset(50%) alone is not sufficient — it doesn't work in some older screen reader + browser combos without the other properties.
4. Provide .sr-only-focusable which undoes the hiding on :focus and :focus-within — required for skip links and "skip to main content" patterns.
5. Show three usage examples in HTML:
   a) An icon-only button with  for the label.
   b) A status badge that appends extra context: (status: online).
   c) A skip link: Skip to main content.
6. Show an aria-live region with class="sr-only" for announcing dynamic changes.

Constraints:
- Do not use text-indent: -9999px — it causes a horizontal scrollbar in RTL languages.
- font-size: 0 does not work in some screen readers.
- The clip property is deprecated but still needed for max compatibility alongside clip-path: inset(50%).

Output the CSS class and all three HTML usage examples with brief comments.

Why this matters in 2026

Icon-only buttons, status indicators, progress bars, and notification badges carry visual meaning that sighted users parse at a glance. Screen reader users navigate the same interface through the accessibility tree — if an icon button has no text label, it is announced as "button" with no action. The .sr-only pattern bridges this gap: text that lives in the DOM (and therefore in the accessibility tree) but is visually collapsed to a single pixel so it doesn't affect the layout.

The logic

The critical properties are position: absolute (removes from flow), width: 1px; height: 1px (collapses to a point), overflow: hidden; clip: rect(0,0,0,0) (clips any visible overflow), and white-space: nowrap (prevents text from wrapping to a larger height). margin: -1px accounts for any border-box edge case. Do not use display: none or visibility: hidden — both remove elements from the accessibility tree entirely. The sr-only-focusable variant simply undoes the hiding when the element receives focus, making it visible to keyboard users at the moment they tab to it — the classic skip-link pattern.

Accessibility & performance

Elements with .sr-only are part of the document flow as positioned elements and have effectively zero layout impact. They do not affect paint, compositing, or line-box calculations. The pattern is WCAG 1.1.1 compliant for non-text content and the recommended approach in the WAI-ARIA Authoring Practices Guide. For dynamic content announcements, combine .sr-only with aria-live="polite" — the element is invisible but the screen reader announces text updates as they appear in the DOM.