Tips & Tricks (Aktualisiert: 2.6.2026)

Barrierefreiheit mit Claude Code: HTML, ARIA, axe und manuelle Prüfung

Praxis-Workflow für Barrierefreiheit mit Claude Code: HTML, Tastatur, Formulare, Fokus, axe und Screenreader.

Barrierefreiheit mit Claude Code: HTML, ARIA, axe und manuelle Prüfung

Barrierefreiheit ist keine Aufgabe, bei der man kurz vor dem Release ein Tool startet und ein paar Warnungen behebt. Sie beginnt bei semantischem HTML, geht weiter über Tastaturbedienung, Fokusführung, Formularfehler und Farbkontrast und endet erst nach automatisierten Checks und manueller Prüfung mit Screenreader.

Claude Code kann diesen Ablauf stark beschleunigen. Dafür muss die Aufgabe aber präzise sein. Ein Prompt wie “mach die Komponente barrierefrei” führt leicht zu einem div mit ARIA, aber ohne Enter- oder Space-Verhalten, zu einem Modal ohne saubere Fokusrückgabe oder zu Fehlermeldungen, die sichtbar sind, aber nicht vorgelesen werden.

Als Grundlage dienen offizielle Quellen: W3C WCAG 2.2 als praktisches Ziel, der WAI-ARIA Authoring Practices Guide für Widget-Patterns, MDN ARIA für “semantisches HTML zuerst”, die Deque axe-core Dokumentation für automatisierte Tests und die Claude Code Dokumentation für die Tool-Grundlagen.

Ziel vor dem Patch festlegen

“Barrierefreiheit verbessern” ist zu ungenau. Ein brauchbares Ziel lautet: WCAG 2.2 AA als Arbeitsstandard, semantisches HTML vor ARIA, Kernpfade vollständig per Tastatur bedienbar, sichtbarer Fokus, verständliche Fehler und Nachweis durch automatische plus manuelle Prüfung.

BereichPraktischer MaßstabTypischer Fehler
Semantisches HTMLbutton, a, form, label, main, nav korrekt einsetzenKlickbares div ersetzt native Kontrolle
TastaturTab, Shift+Tab, Enter, Space und Escape decken den Hauptfluss abModal schließt nur mit Maus
FokusFokus geht in neue UI und kehrt zum Auslöser zurückFokus landet hinter dem Dialog
ARIANur ergänzen, wenn HTML den Zustand nicht ausdrücktaria-label verdeckt fehlendes sichtbares Label
FarbeText, Kontrollen, Fehler und Fokus sind sichtbarFehler wird nur durch Rot vermittelt
FormulareLabels, Hinweise, Invalid-State und Fehler sind mit Inputs verbundenFehler wird angezeigt, aber nicht angekündigt
Testsaxe plus Tastatur und ScreenreaderKeine automatischen Verstöße wird als vollständiger Audit missverstanden

MDN empfiehlt, native HTML-Elemente zu verwenden, wenn sie die benötigte Semantik und das Verhalten bereits liefern. Claude Code sollte deshalb zuerst Struktur reparieren und ARIA nur für fehlende Zustände wie aria-invalid, aria-expanded oder aria-modal ergänzen.

Sicherer Claude-Code-Prompt

Ein guter Prompt ist eine Review-Anweisung mit Grenzen. Er schützt Business-Inhalte, nennt den Standard und verlangt Belege.

claude <<'PROMPT'
Scope:
- Review only src/components/CheckoutForm.tsx and its tests.
- Do not change pricing copy, analytics events, or unrelated styles.

Accessibility target:
- Use WCAG 2.2 AA as the practical target.
- Prefer semantic HTML before ARIA.
- Add ARIA only when native HTML cannot express the state.

Check these items:
- Labels, descriptions, required state, and validation errors.
- Keyboard operation with Tab, Shift+Tab, Enter, Space, and Escape.
- Focus order, visible focus, and focus return after closing UI.
- Color contrast and non-color error indicators.
- Automated axe check plus manual screen-reader notes.

Output:
- Findings first, with file and line references.
- Minimal patch.
- Commands to verify.
- Any remaining risk.
PROMPT

Findings first ist entscheidend. Claude Code soll erst den Defekt erklären und danach den kleinsten Patch liefern. Das schützt Seiten mit Preisen, CTA, Gumroad-Links oder Analytics-Events vor unnötigen Umbauten. Mehr zu kleinen, überprüfbaren Aufgaben steht in den Claude Code Produktivitätstipps.

Use Case 1: Produkt-CTA oder Artikel-CTA

Ein CTA ist oft Umsatzpfad. Wenn er navigiert, braucht er einen echten Link, nicht eine ganze Karte mit onclick.

<div class="hero-card" onclick="location.href='/en/products'">
  <div class="title">Claude Code Templates</div>
  <div class="button">Buy now</div>
</div>

Die robuste Variante trennt Überschrift, Nutzen und Ziel.

<section aria-labelledby="templates-heading" class="product-cta">
  <h2 id="templates-heading">Reviews mit Claude-Code-Vorlagen verkürzen</h2>
  <p>
    Kopieren Sie wiederverwendbare Prompts für Implementierung,
    Review, Debugging und Dokumentation.
  </p>
  <a class="primary-link" href="/en/products">
    Produktressourcen ansehen
  </a>
</section>

Sag Claude Code ausdrücklich, dass Ziel-URLs, Tracking-Attribute und CTA-Text erhalten bleiben müssen. Ein barrierefreier Patch, der den Conversion-Pfad beschädigt, ist kein guter Patch.

Use Case 2: Kontakt- oder Beratungsformular

Formulare verbinden Barrierefreiheit und Umsatz. Wenn Label, Format, Fehler oder Korrekturhinweis unklar sind, bricht der Nutzer die Anfrage ab.

import { FormEvent, useState } from "react";

type Errors = {
  name?: string;
  email?: string;
};

export function ConsultationForm() {
  const [errors, setErrors] = useState<Errors>({});

  function handleSubmit(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    const data = new FormData(event.currentTarget);
    const nextErrors: Errors = {};

    if (!String(data.get("name") || "").trim()) {
      nextErrors.name = "Bitte geben Sie Ihren Namen ein.";
    }

    if (!String(data.get("email") || "").includes("@")) {
      nextErrors.email = "Bitte geben Sie eine gültige E-Mail-Adresse ein.";
    }

    setErrors(nextErrors);
  }

  return (
    <form aria-labelledby="consultation-title" onSubmit={handleSubmit} noValidate>
      <h2 id="consultation-title">Beratungsanfrage</h2>

      <div className="field">
        <label htmlFor="name">Name</label>
        <input
          id="name"
          name="name"
          autoComplete="name"
          aria-invalid={errors.name ? "true" : "false"}
          aria-describedby={errors.name ? "name-error" : undefined}
        />
        {errors.name && (
          <p id="name-error" role="alert">
            {errors.name}
          </p>
        )}
      </div>

      <div className="field">
        <label htmlFor="email">E-Mail</label>
        <p id="email-help">Nutzen Sie eine Adresse, unter der wir antworten können.</p>
        <input
          id="email"
          name="email"
          type="email"
          autoComplete="email"
          aria-invalid={errors.email ? "true" : "false"}
          aria-describedby={
            errors.email ? "email-help email-error" : "email-help"
          }
        />
        {errors.email && (
          <p id="email-error" role="alert">
            {errors.email}
          </p>
        )}
      </div>

      <button type="submit">Anfrage senden</button>
    </form>
  );
}

Der häufigste Fehler ist eine sichtbare Fehlermeldung ohne Verbindung zum Input. Der zweite ist ein dauerhaft referenziertes Fehler-ID, obwohl das Element noch nicht existiert. Dauerhafte Hilfe bleibt immer verknüpft, Fehler erst im Fehlerfall.

Use Case 3: Modal, Command Palette und Menü

Beim Modal zählt nicht nur die Optik. Der offizielle Dialog Modal Pattern verlangt: Fokus geht hinein, Tab bleibt im Dialog, Escape schließt, Fokus kehrt zum Auslöser zurück.

import { ReactNode, useEffect, useRef } from "react";

type ModalProps = {
  open: boolean;
  title: string;
  onClose: () => void;
  children: ReactNode;
};

const focusableSelector = [
  "a[href]",
  "button:not([disabled])",
  "input:not([disabled])",
  "select:not([disabled])",
  "textarea:not([disabled])",
  '[tabindex]:not([tabindex="-1"])',
].join(",");

export function AccessibleModal(props: ModalProps) {
  const { open, title, onClose, children } = props;
  const dialogRef = useRef<HTMLDivElement>(null);
  const previousFocusRef = useRef<HTMLElement | null>(null);

  useEffect(() => {
    if (!open) return;

    previousFocusRef.current = document.activeElement as HTMLElement;
    const focusable = dialogRef.current?.querySelectorAll<HTMLElement>(
      focusableSelector
    );
    focusable?.[0]?.focus();

    function onKeyDown(event: KeyboardEvent) {
      if (event.key === "Escape") onClose();
      if (event.key !== "Tab" || !dialogRef.current) return;

      const items = [...dialogRef.current.querySelectorAll<HTMLElement>(
        focusableSelector
      )];
      const first = items[0];
      const last = items[items.length - 1];

      if (event.shiftKey && document.activeElement === first) {
        event.preventDefault();
        last?.focus();
      } else if (!event.shiftKey && document.activeElement === last) {
        event.preventDefault();
        first?.focus();
      }
    }

    document.addEventListener("keydown", onKeyDown);
    return () => {
      document.removeEventListener("keydown", onKeyDown);
      previousFocusRef.current?.focus();
    };
  }, [open, onClose]);

  if (!open) return null;

  return (
    <div className="modal-backdrop">
      <div
        ref={dialogRef}
        role="dialog"
        aria-modal="true"
        aria-labelledby="modal-title"
        className="modal-panel"
      >
        <h2 id="modal-title" tabIndex={-1}>
          {title}
        </h2>
        {children}
        <button type="button" onClick={onClose}>
          Schließen
        </button>
      </div>
    </div>
  );
}

Bei Menüs ist Vorsicht nötig. Der Menu Button Pattern passt zu Befehlsmenüs. Normale Website-Navigation ist oft besser als nav mit Links umgesetzt.

Farbe, Fokus und Mobile

Viele Regressionen entstehen in der Design-Politur: outline: none, graue Texte, Fehler nur in Rot. Sichtbarer Fokus braucht eine klare Alternative.

.primary-link {
  background: #0f766e;
  border-radius: 6px;
  color: #ffffff;
  display: inline-flex;
  font-weight: 700;
  min-height: 44px;
  padding: 0.75rem 1rem;
}

.primary-link:focus-visible,
button:focus-visible,
input:focus-visible {
  outline: 3px solid #f59e0b;
  outline-offset: 3px;
}

.field [role="alert"] {
  border-left: 4px solid #b91c1c;
  color: #7f1d1d;
  margin-top: 0.5rem;
  padding-left: 0.75rem;
}

Prüfe auch mobile Breiten. Zu kleine Close-Buttons, Fokus unter Sticky Headern oder zu schmale CTA-Flächen fallen am Desktop schnell durch.

axe und manuelle Prüfung

axe findet strukturelle Fehler schnell. Es beweist nicht, dass Texte verständlich sind oder die Lesereihenfolge für den Geschäftsfluss passt.

npm install -D @axe-core/playwright @playwright/test
npx playwright install --with-deps chromium
import AxeBuilder from "@axe-core/playwright";
import { expect, test } from "@playwright/test";

test("consultation form has no serious accessibility issues", async ({ page }) => {
  await page.goto("/contact");

  const results = await new AxeBuilder({ page })
    .include("main")
    .withTags(["wcag2a", "wcag2aa", "wcag22aa"])
    .analyze();

  expect(results.violations).toEqual([]);
});

Manuell prüfst du zuerst Produkt-CTA, Formular, Checkout, Modal, Navigation und Fehlerkorrektur. Unter Windows ist NVDA ein guter Start, unter macOS VoiceOver.

Konkrete Fehlerliste

  • role="button" ohne Enter- und Space-Unterstützung.
  • Icon-Button ohne zugänglichen Namen.
  • Nutzloser Alternativtext wie alt="image".
  • aria-hidden="true" versteckt Modal oder Live Region.
  • Fehlertext ist sichtbar, aber nicht mit aria-describedby verbunden.
  • Fokusdarstellung wurde entfernt.
  • Modal gibt Fokus nicht an den Auslöser zurück.
  • Automatischer Check prüft nur Marketingseite, nicht das echte Formular.

Diese Liste kannst du Claude Code direkt nach dem Patch geben und um Datei- und Zeilenangaben bitten.

CTA und Praxisergebnis

Für wiederholbare Workflows starte mit den Claude Code Produkten. Wenn Review- und Debugging-Prompts ständig wiederkehren, helfen die 50 Claude-Code-Prompt-Vorlagen. Für Team-Rollout mit Permissions, Hooks und Verification Receipts ist Beratung sinnvoll.

Für diese Aktualisierung habe ich drei reale Fehler nachgestellt: eine CTA-Karte als klickbares div, ein Formular mit nicht angekündigten Fehlern und ein Modal ohne Fokusrückgabe. Am stabilsten war: Claude Code zuerst Findings liefern lassen, dann minimalen Patch erstellen, danach Tastatur und VoiceOver prüfen. axe hat Strukturfehler gefunden, aber die Verständlichkeit des Flows blieb manuelle Arbeit.

#Claude Code #accessibility #WCAG #a11y #React
Kostenlos

Kostenloses PDF: Claude-Code-Cheatsheet

E-Mail eintragen und eine Seite mit Befehlen, Review-Gewohnheiten und sicheren Workflows herunterladen.

Wir schützen Ihre Daten und senden keinen Spam.

Masa

Über den Autor

Masa

Engineer für praktische Claude-Code-Workflows und Team-Einführung.