Skip to content
AgileLogics
7 min read

Accessibility and CSS

Prerequisites: Responsive design and media queries

CSS can make an accessible page unusable — or make a good one excellent.

Contrast

  • Text: at least 4.5:1 against its background (3:1 for large text, about 24px, or 18.7px bold).
  • Interface components and focus indicators: at least 3:1 against adjacent colors.
  • Check text over images and gradients at their lightest point.
  • Placeholder text and disabled states are common failures.

Visible focus

:focus-visible {
  outline: 3px solid var(--focus, #f5a623);
  outline-offset: 2px;
}

.card:has(a:focus-visible) {
  outline: 3px solid var(--focus, #f5a623);
}

Never remove outlines without a replacement. outline is also kept in forced-colors mode, where box-shadow focus rings disappear.

Respect user preferences

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

@media (forced-colors: active) {
  .button { border: 1px solid ButtonText; }
  .icon { forced-color-adjust: auto; }
}
  • prefers-reduced-motion — the durations are near zero rather than none, so animationend/transitionend events still fire for scripts that wait for them.
  • forced-colors (Windows contrast themes) replaces your colors with the user's system colors. Backgrounds disappear, so shapes defined only by background color (buttons, toggles) need a real border.

Zoom and text resizing

  • Size text in rem; never block zooming.
  • Layouts must work at 400% zoom (a 320-pixel-wide viewport) without horizontal scrolling for normal text content — WCAG's "reflow" requirement.
  • Don't set fixed heights on text containers; let them grow.
  • Line height at least 1.5 for body text, and text must survive users overriding letter-spacing and word-spacing.

Visual order vs DOM order

order, flex-direction: row-reverse, grid-auto-flow: dense, and explicit grid placement can make the visual order differ from the source order that keyboard and screen-reader users follow. Keep them matching. (The new reading-flow property lets focus follow the visual order of flex and grid items; support is still limited to Chromium.)

Hiding content correctly

Goal Use
Hide from everyone display: none or the hidden attribute
Hide visually, keep for screen readers A .visually-hidden class
Hide decorative content from screen readers aria-hidden="true" in the HTML

content in ::before/::after may be read aloud — don't put decorative emoji there without an empty alternative (content: "✨" / "").

Target sizes

Make interactive targets at least 24 × 24 CSS pixels (WCAG 2.2 AA), ideally 44 × 44 on touch screens. Padding on links and buttons counts.

Test

Use DevTools' Rendering panel to emulate reduced motion, forced colors, dark mode, and color vision deficiencies; zoom to 400%; and check contrast with the color picker in the Styles panel.