Skip to main content
PimentCSS v1.0.1, what's new
Home

Accessibility guide

Focus rings, touch targets, semantic contrast pairs, and reduced motion.

Overview

Accessibility is built into the token layer, not added per component. Override tokens or Sass variables when branding; re-check focus, contrast, and motion after theme changes.

ConcernToken / APIWCAG
Keyboard focus--focus-ring, .focus-visible2.4.7 Focus visible
Touch size--min-touch-target (44px)2.5.5 Target size (AAA target, AA practice)
Text contrastSemantic fg/bg pairs1.4.3 Contrast (minimum)
Motionprefers-reduced-motion2.3.3 Animation from interactions
Screen reader text.sr-only1.3.1 Info and relationships
Hidden content[hidden] + display: none4.1.2 Name, role, value

Prerequisites

  • PimentCSS installed, Installation (a11y tokens ship in the default bundle).
  • Semantic colors, Colors for surfaces and text tokens used in contrast pairs.
  • Both themes, toggle light/dark in the doc header while reviewing focus and swatches below.

Canonical tokens

Edit tokens/a11y.css for focus, motion, and documented contrast aliases. Sass source: scss/tokens/_a11y.scss.

Visible focus

Interactive elements use :focus-visible (not :focus on every click) with a 3px ring. Apply .focus-visible on custom controls or use the focus-ring mixin in Sass. In documentation previews, .focus-visible simulates the ring without tabbing.

Link

Tab through the demo above to see live :focus-visible on each control.

Touch targets

Buttons, checkboxes, radios, switches, and theme toggles respect min-height: var(--min-touch-target) (44px). Icon-only buttons use the same minimum square size via .btn--icon-only.

Contrast pairs

Use semantic foreground/background tokens in UI. Target ≥ 4.5:1 for normal text (AA). Large text (≥ 18px regular or 14px bold) may use 3:1. Non-text UI boundaries and focus indicators need ≥ 3:1 against adjacent colors (WCAG 1.4.11).

--surface-page Body copy
--surface-action Primary button
--error-100 Inline error
--surface-elevated Card surface
UsageTextBackgroundTarget
Page body--text-body--surface-pageAA 4.5:1
Primary button--text-on-action--surface-actionAA 4.5:1
Error message--error-700--error-100AA 4.5:1
Success on tint--success-900--success-100AA 4.5:1

Full palette and live ratios: Colors → Semantic contrast pairs.

Screen reader only

Supplement visible labels with .sr-only when context is missing visually (icon-only buttons, redundant link text). Documentation chrome uses .pdoc-sr-only with the same clipping pattern.

Hidden content

Always use the native hidden attribute (or aria-hidden="true" for decorative icons). Global CSS sets [hidden] { display: none !important; } so collapsed tree groups and loaders do not remain focusable.

Reduced motion

When users enable Reduce motion at the OS level, animations and transitions are minimized site-wide:

Avoid animating large properties (box-shadow, width) for state changes; prefer opacity, border, or instant swaps. Test carousels, loaders, and snackbars with reduced motion enabled.

Utilities & classes

ClassRole
.focus-visibleApplies --focus-ring on :focus-visible
.sr-onlyVisually hidden, available to assistive tech

Customize (Sass)

  1. Override focus and touch tokens

    Pass variables when importing PimentCSS. Keep ring width ≥ 2px and sufficient contrast against adjacent surfaces.
    @use "pimentcss-design-system" with (
      $focus-ring-width: 3px,
      $focus-ring-color: var(--accent-500),
      $min-touch-target: 44px,
    );
  2. Rebuild CSS

    Regenerate dist/pimentcss.min.css after token edits.
    npm run build:css

See Customization for partial imports. Components use @include focus-ring and @include touch-target from scss/abstracts/_mixins.scss.

Review checklist

Before shipping UI

  • Keyboard, tab order logical; focus visible on every interactive control; no focus trap without escape.
  • Names, buttons and links have accessible names; form fields have associated <label> or aria-label.
  • Color, do not rely on hue alone; pair with text, icons, or weight (RGAA thématique 3).
  • Contrast, verify light and dark; use semantic tokens from Colors.
  • Motion, test with prefers-reduced-motion: reduce.
  • Dialogs, role="dialog", aria-modal="true", focus management, see Modals.

Next steps