CP Registry

Barrierefreiheit (A11y)

WCAG 2.1 AA Konformität ist das Ziel. Diese Seite dokumentiert die A11y-Strategien, -Tools und -Anforderungen des Systems.

A11y-Utilities

Wiederverwendbare Scripts unter src/components/a11y/:

utils.ts

Basis-Helfer: typisierte Query-Selectors (qsa, qs), uid() für einzigartige IDs, ensureId() für Auto-IDs, getFocusable() für alle fokussierbaren Elemente, Keyboard-Event-Helfer (isEnter, isEscape, isTab, isArrowDown etc.), prefersReducedMotion().

focus-trap.ts

Focus-Trap für modale Elemente (Dialog, Mobile Nav). createFocusTrap(container) gibt activate() und deactivate() zurück. Tab/Shift+Tab cycled durch fokussierbare Elemente innerhalb des Containers.

live-region.ts

Screen-Reader Announcements: announce('5 Ergebnisse gefunden') erstellt eine aria-live Region und liest den Text vor. Wichtig für dynamische Inhalts-Updates (Galerie-Wechsel, Filter-Ergebnisse).

aria-toggle.ts

Universelles Toggle für aria-expanded/aria-hidden Paare. Nutzt data-toggle-trigger und data-toggle-target Attribute. Keyboard: Enter/Space zum Toggeln, Escape zum Schliessen.

scroll-reveal.ts

IntersectionObserver für Scroll-Animationen. Bei prefers-reduced-motion: reduce werden alle Elemente sofort sichtbar (keine Animation). Elemente sind für Screen-Reader immer lesbar.

WCAG 2.1 AA Anforderungen

1. Wahrnehmbar

  • 1.1 Textalternativen: Alle Bilder haben Alt-Texte. Dekorative Bilder: alt=""
  • 1.3 Anpassbar: Semantisches HTML (<nav>, <main>, <article>). Korrekte Heading-Hierarchie
  • 1.4.3 Kontrast: Mindestens 4.5:1 für Text, 3:1 für großen Text. Brand-Tokens erfüllen dies
  • 1.4.4 Textgroesse: Fluid Typography mit clamp() — skaliert mit Viewport
  • 1.4.10 Reflow: Kein horizontales Scrollen bis 320px Viewport. Content-Grid handhabt das
  • 1.4.11 Non-text Contrast: Focus-Ringe, Buttons, Borders haben 3:1 Kontrast

2. Bedienbar

  • 2.1.1 Tastatur: Alle Funktionen sind per Tastatur bedienbar. Components implementieren Arrow-Keys, Enter, Space, Escape
  • 2.1.2 Keine Tastaturfalle: Focus-Traps (Modal, Mobile Nav) haben immer einen Ausweg (Escape)
  • 2.4.1 Skip Link: "Zum Inhalt springen" Link am Seitenanfang (in Layout.astro)
  • 2.4.3 Fokusreihenfolge: Tab-Reihenfolge entspricht der visuellen Reihenfolge
  • 2.4.7 Fokus sichtbar: :focus-visible Ring auf allen interaktiven Elementen (in reset.css)
  • 2.3.1 Keine Blitze: Keine blinkenden Elemente. Animationen respektieren prefers-reduced-motion

3. Verstaendlich

  • 3.1.1 Sprache: <html lang="de"> auf jeder Seite
  • 3.2.1 Bei Fokus: Kein Kontextwechsel bei Fokus-Erhalt
  • 3.3.1 Fehlererkennung: Input-Component zeigt Fehler mit aria-describedby
  • 3.3.2 Labels: Jedes Formularfeld hat ein sichtbares Label

4. Robust

  • 4.1.1 Parsing: Valides HTML. Keine doppelten IDs (uid() generiert einzigartige)
  • 4.1.2 Name, Rolle, Wert: ARIA-Attribute auf allen interaktiven Components (role, aria-expanded, aria-selected, aria-controls)

A11y pro Component

Component ARIA Pattern Keyboard Besonderheiten
Accordion <details> + <summary> Enter/Space Native HTML, kein ARIA nötig
Tabs Roving Tabindex Arrow Left/Right, Home/End role="tablist", aria-selected
Dialog Native <dialog> Escape schließt, Tab-Trap Focus-Trap, Scroll-Lock, Focus-Restore
Navigation <nav aria-label> Escape schließt Mobile Focus-Trap im Mobile-Menu, aria-expanded
Gallery role="list" + <dialog> Arrow Left/Right in Lightbox Live-Region für Bildwechsel-Announcements
Card Clickable Card Pattern Tab + Enter auf Link Focus-Ring auf <article>, nicht auf Link
Button <button> / <a> Enter/Space :focus-visible Ring, Loading-State mit aria-busy
Input Label + aria-describedby Standard-Form-Tab Error-Messages verknüpft via ID

Testen

Automatisiert

  • axe-core: Im Test-Setup integriert (pnpm test)
  • Lighthouse: Chrome DevTools → Lighthouse → Accessibility
  • WAVE: Browser-Extension für Seiten-Audits

Manuell

  • Tastatur-Test: Seite nur mit Tab, Enter, Space, Escape, Pfeiltasten bedienen
  • Screen-Reader: VoiceOver (macOS) oder NVDA (Windows)
  • Zoom: Seite auf 200% vergrößern — darf nicht brechen
  • Farbfilter: Simulation von Farbenblindheit (Chrome DevTools)

prefers-reduced-motion

Das System respektiert die Benutzer-Einstellung für reduzierte Bewegung:

  • reset.css: Setzt animation-duration und transition-duration global auf 0.01ms
  • scroll-reveal.ts: Zeigt alle Elemente sofort (keine Scroll-Animation)
  • Gallery Lightbox: Kein Scale-Overgang bei Dialog-Open
  • Navigation: Kein Slide-Übergang im Mobile-Menu

Testen: macOS → Systemeinstellungen → Bedienungshilfen → Anzeige → "Bewegung reduzieren"