Community Question Bundle
The CSS Accessibility Tricks I Keep Using
Five accessibility moves I have committed to muscle memory: the visually-hidden snippet, skip links, focus-visible rings, reduced-motion, and a CSS variable trick that catches contrast bugs at build time.
The CSS Accessibility Tricks I Keep Using
Five accessibility moves I have committed to muscle memory: the visually-hidden snippet, skip links, focus-visible rings, reduced-motion, and a CSS variable trick that catches contrast bugs at build time.
By @arjunrivera
November 21, 2025
·
Updated May 18, 2026
730 views
6
4.0 (10)
I need a class that visually hides content but keeps it readable by screen readers. The naive display: none hides it from everyone. Write the modern snippet I drop into every project, and explain why display: none and visibility: hidden are both wrong.
What I want to see
The .sr-only (or .visually-hidden) pattern: 1px box, clipped, absolutely positioned, no border, overflow hidden, no whitespace. Both display: none and visibility: hidden remove the element from the accessibility tree.
Audit flagged that keyboard users have to tab through the entire navigation before reaching main content on every page load. Add a skip link that is invisible until focused, then jumps to the main content.
What I want to see
A skip link that uses the .sr-only recipe by default and reveals on :focus (or :focus-visible). The visible state moves the link into the viewport with a real position and a strong contrast.
Design lead asked me to remove all focus rings because they 'look ugly on mouse click'. The accessibility audit will fail if I do. Write the rule that keeps focus rings for keyboard users but hides them for mouse clicks.
What I want to see
:focus-visible only paints when the browser heuristically decides the focus came from keyboard (or touch on some platforms). Pair it with :focus:not(:focus-visible) to remove the outline on mouse-driven focus.
A user reported vestibular issues with the parallax hero on our landing page. Wrap the animations so users who prefer reduced motion get a still version. Bonus: show the JavaScript pattern for honoring the same preference in a non-CSS animation library.
What I want to see
The @media (prefers-reduced-motion: reduce) query that either disables animations or replaces them with a fade. The JS pattern uses matchMedia('(prefers-reduced-motion: reduce)') and listens for changes.
Design tokens ship as CSS custom properties: --text-primary, --bg-primary. Every dark-mode override I review at least once breaks WCAG contrast. Show a CSS-only pattern that makes the contrast check visible at build time (or at least at devtools time), and explain why hand-checking every pair does not scale.
What I want to see
The color-contrast() CSS function for browsers that support it; for older targets, name the alternative: a CSS variable for the contrast pair plus a documented build step (Stylelint plugin, automated Pa11y/axe test) that fails CI on a contrast regression.
