CSS for Accessibility (WCAG 2.2) & Print Styles

Engineer inclusive digital experiences with keyboard focus indicators, user preference media queries, screen-reader optimizations, and clean print document stylesheets.

1. WCAG 2.2 Guidelines: Contrast & Focus Indicators

The Web Content Accessibility Guidelines (WCAG) mandate visual criteria that stylesheets must satisfy to be legally compliant (ADA, Section 508, European Accessibility Act):

  • Contrast Minimum (Level AA): Regular body text requires at least a 4.5:1 contrast ratio against its background. Large text (≥18pt or ≥14pt bold) and active UI components (input borders, button outlines) require at least 3:1.
  • Enhanced Contrast (Level AAA): Regular text requires at least 7:1, large text requires 4.5:1.
  • Focus Visibility (Criterion 2.4.7 & 2.4.11): Any keyboard-operable interface element must have a prominent visual focus indicator.
The Magic of :focus-visible

Previously, designers disabled outlines with outline: none because mouse clicks triggered focus rings. The modern :focus-visible pseudo-class solves this conflict: it activates only when the user navigates via keyboard (Tab / Shift+Tab) or assistive switch controls, staying hidden during mouse clicks!

CSS Example

/* Accessible focus indicator with :focus-visible */
.nav-link-btn {
  display: inline-block;
  padding: 10px 18px;
  background-color: #2563eb;
  color: #ffffff;
  border-radius: 6px;
  text-decoration: none;
  font-weight: 600;
  border: none;
  outline: 3px solid transparent;
  outline-offset: 3px;
  transition: all 0.2s ease;
}

/* Shown ONLY during keyboard tabbing */
.nav-link-btn:focus-visible {
  outline-color: #2563eb;
  box-shadow: 0 0 0 4px rgba(37, 99, 235, 0.25);
}

2. User Preference Media Queries

Modern operating systems allow users to declare environmental and physical preferences. CSS provides dedicated media queries to adapt automatically:

Media FeatureSystem Preference DetectedRecommended CSS Response
prefers-reduced-motionUser requests minimal animations due to vestibular sensitivity or motion sickness.Set animation-duration: 0.01ms and transition-duration: 0.01ms to eliminate movement.
prefers-color-schemeUser selected Dark Mode or Light Mode in OS settings.Adjust CSS variables (--bg-color, --text-color) to provide dark/light themes.
prefers-contrastUser requested increased or decreased visual contrast.Darken text, increase border thicknesses, and remove low-contrast subtle gradients.
forced-colorsWindows High Contrast Mode (WHCM) is active.Ensure system colors (ButtonText, Canvas) render clearly; avoid overriding with opaque backgrounds.
/* Accessible User Preference Integration */
@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 (prefers-color-scheme: dark) {
  :root {
    --bg-page: #0f172a;
    --text-page: #f8fafc;
  }
}

3. The Screen-Reader-Only Utility Pattern (.visually-hidden)

Sometimes visual designs omit labels (e.g. an icon-only search magnifying glass button). However, screen reader users require descriptive text.

Never use display: none or visibility: hidden to hide text meant for screen readers, because these properties remove the node entirely from the accessibility tree.

The Battle-Tested .visually-hidden / .sr-only Pattern:
.visually-hidden {
  position: absolute !important;
  width: 1px !important;
  height: 1px !important;
  padding: 0 !important;
  margin: -1px !important;
  overflow: hidden !important;
  clip: rect(0, 0, 0, 0) !important;
  white-space: nowrap !important;
  border: 0 !important;
}

4. Professional Print Stylesheets (@media print)

When users print a webpage (or export to PDF via Ctrl+P), stylesheets should strip irrelevant screen clutter, optimize contrast for ink, and format pages cleanly:

Essential Print Rules:
  1. Hide Interactive Clutter: Hide navigation bars, hamburger menus, sidebars, cookie consent banners, audio/video players, and advertisements.
  2. Display Full Hyperlink URLs: On paper, users cannot click links! Reveal link destinations using attr(href).
  3. Prevent Awkward Page Breaks: Keep headings and figures from splitting across printed sheets using CSS fragmentation properties.
@media print {
  /* 1. Hide web-only UI */
  nav, footer, .sidebar, .cookie-banner, .btn, .no-print {
    display: none !important;
  }

  /* 2. Optimize colors and background for ink saving */
  body {
    background: #ffffff !important;
    color: #000000 !important;
    font-size: 12pt;
    line-height: 1.5;
  }

  /* 3. Reveal link targets on paper */
  a[href^="http"]::after {
    content: " (" attr(href) ")";
    font-size: 9pt;
    color: #555;
  }

  /* 4. Page Break Management */
  h1, h2, h3 {
    break-after: avoid;
    page-break-after: avoid;
  }

  blockquote, pre, img, figure, table {
    break-inside: avoid;
    page-break-inside: avoid;
  }

  /* 5. Set physical sheet margins */
  @page {
    margin: 2cm;
    size: letter portrait;
  }
}

5. Frequently Asked Questions (FAQ)

When Windows High Contrast Mode (WHCM) is enabled, the browser ignores all developer-specified background-color, color, and box shadows, substituting them with high-contrast system colors. Ensure elements use semantic borders so boxes remain distinguishable in WHCM.

Browser zoom (Ctrl + '+') scales the entire CSS viewport (including pixel values). In contrast, changing default font size in browser settings (e.g. 24px default) only affects font-relative units like rem and em. Using rem ensures users who need larger text are respected.

break-inside: avoid instructs the printing engine not to split a table, image, card, or code block across two printed physical sheets of paper. If the element cannot fit on the remainder of the current page, it pushes the entire element to the top of the next page.

Explore Related Tools

Hand-picked utilities and calculators related to this tool.

Related Tools