Barrierefreie Website BFSG 2025: Technische Anforderungen & Code-Beispiele
Das Barrierefreiheitsstärkungsgesetz (BFSG) verpflichtet ab dem 28. Juni 2025 alle Unternehmen mit mehr als 10 Mitarbeitern oder einem Jahresumsatz über 2 Millionen Euro zur barrierefreien Gestaltung ihrer digitalen Dienste. Für Entwickler und technische Entscheider bedeutet dies: WCAG 2.1 Level AA Konformität ist Pflicht.
Dieser Guide zeigt Ihnen konkrete technische Umsetzung mit Code-Beispielen, Testing-Tools und Best Practices für BFSG-konforme Websites.
Was bedeutet BFSG technisch?
Die rechtliche Grundlage
- Gesetz: Barrierefreiheitsstärkungsgesetz (BFSG)
- Deadline: 28. Juni 2025
- Standard: WCAG 2.1 Level AA (Web Content Accessibility Guidelines)
- Strafen: Bis zu 100.000€ Bußgeld + Abmahnrisiko
- Betroffen: Online-Shops, Websites, Web-Apps, digitale Dienstleistungen
WCAG 2.1 Level AA: Die 4 Prinzipien
Die WCAG basiert auf 4 Grundprinzipien (POUR):
- Perceivable (Wahrnehmbar): Inhalte müssen für alle Sinne zugänglich sein
- Operable (Bedienbar): Navigation ohne Maus möglich
- Understandable (Verständlich): Klare Sprache, konsistente Bedienung
- Robust (Robust): Kompatibel mit assistiven Technologien
1. Semantisches HTML: Die Basis jeder barrierefreien Website
Problem: Div-Suppe ohne Struktur
❌ Falsch (nicht barrierefrei):
<div class="header">
<div class="nav">
<div class="link">Home</div>
<div class="link">Über uns</div>
</div>
</div>
<div class="content">
<div class="article">
<div class="title">Artikel-Überschrift</div>
<div class="text">Artikeltext...</div>
</div>
</div>
Warum ist das schlecht?
- Screen Reader können Struktur nicht erkennen
- Keine semantische Navigation möglich
- Suchmaschinen verstehen Hierarchie nicht
- Keine Landmark-Navigation
Lösung: Semantische HTML5-Elemente
✅ Richtig (barrierefrei):
<header>
<nav aria-label="Hauptnavigation">
<ul>
<li><a href="/">Home</a></li>
<li><a href="/ueber-uns">Über uns</a></li>
</ul>
</nav>
</header>
<main>
<article>
<h1>Artikel-Überschrift</h1>
<p>Artikeltext...</p>
</article>
</main>
<footer>
<p>© 2025 Wendermedia</p>
</footer>
Vorteile:
- Screen Reader erkennen Landmarks (
<main>,<nav>,<header>,<footer>) - Nutzer können direkt zum Hauptinhalt springen
- Bessere SEO durch klare Struktur
- Konsistente User Experience
Überschriften-Hierarchie
❌ Falsch:
<h1>Hauptüberschrift</h1>
<h3>Unterüberschrift</h3> <!-- h2 übersprungen! -->
<h2>Weitere Überschrift</h2> <!-- Falsche Reihenfolge -->
✅ Richtig:
<h1>Hauptüberschrift</h1>
<h2>Unterüberschrift Ebene 2</h2>
<h3>Unterüberschrift Ebene 3</h3>
<h3>Weitere Ebene 3</h3>
<h2>Weitere Ebene 2</h2>
WCAG-Kriterium: 1.3.1 Info and Relationships (Level A)
Best Practice:
- Genau eine
<h1>pro Seite (Seitentitel) - Logische Hierarchie ohne Sprünge (h1 → h2 → h3, nicht h1 → h3)
- Keine Überschriften aus rein optischen Gründen
2. Tastaturnavigation: Alles muss bedienbar sein
Fokus-Management
❌ Falsch (Maus-only):
<div onclick="openModal()">Öffnen</div>
Problem: Funktioniert nur mit Maus, nicht mit Tastatur oder Screen Reader.
✅ Richtig (tastaturzugänglich):
<button type="button" onclick="openModal()">Öffnen</button>
Noch besser mit Event-Listener:
<button type="button" id="open-modal">Öffnen</button>
<script>
document.getElementById('open-modal').addEventListener('click', function() {
openModal();
});
// Zusätzlich: Escape-Taste zum Schließen
document.addEventListener('keydown', function(e) {
if (e.key === 'Escape' && modalIsOpen) {
closeModal();
}
});
</script>
Fokus-Sichtbarkeit
❌ Falsch (Fokus unsichtbar):
/* NIEMALS machen! */
*:focus {
outline: none;
}
✅ Richtig (deutlicher Fokus-Indikator):
a:focus, button:focus, input:focus {
outline: 3px solid #0066cc;
outline-offset: 2px;
}
/* Modernes Focus-visible (nur Tastatur) */
a:focus-visible, button:focus-visible, input:focus-visible {
outline: 3px solid #0066cc;
outline-offset: 2px;
box-shadow: 0 0 0 4px rgba(0, 102, 204, 0.2);
}
WCAG-Kriterium: 2.4.7 Focus Visible (Level AA)
Kontrastverhältnis für Fokus-Indikatoren: Mindestens 3:1 zum Hintergrund
Tastatur-Shortcuts
Standard-Tastaturnavigation (muss funktionieren):
- Tab: Nächstes fokussierbares Element
- Shift + Tab: Vorheriges Element
- Enter: Links/Buttons aktivieren
- Leertaste: Buttons/Checkboxen aktivieren
- Pfeiltasten: Dropdown-Menüs, Radio-Buttons
- Escape: Modals/Dialoge schließen
Best Practice für Skip-Links:
<a href="#main-content" class="skip-link">Zum Hauptinhalt springen</a>
<header>...</header>
<main id="main-content">
<!-- Hauptinhalt -->
</main>
<style>
.skip-link {
position: absolute;
top: -40px;
left: 0;
background: #000;
color: #fff;
padding: 8px;
z-index: 9999;
}
.skip-link:focus {
top: 0;
}
</style>
3. Barrierefreie Formulare
Label und Input-Verknüpfung
❌ Falsch:
<div>Name:</div>
<input type="text" placeholder="Ihr Name">
Probleme:
- Screen Reader lesen keine Labels vor
- Placeholder verschwindet bei Eingabe
- Kein Klick auf Label möglich
✅ Richtig:
<label for="name">Name *</label>
<input type="text" id="name" name="name" required
aria-required="true" aria-describedby="name-hint">
<span id="name-hint" class="hint">Bitte Vor- und Nachname eingeben</span>
Fehlermeldungen
❌ Falsch (nur rot färben):
<input type="email" style="border-color: red;">
✅ Richtig (mit ARIA):
<label for="email">E-Mail-Adresse *</label>
<input type="email" id="email" name="email"
aria-invalid="true"
aria-describedby="email-error">
<span id="email-error" role="alert" class="error">
⚠️ Bitte geben Sie eine gültige E-Mail-Adresse ein
</span>
WCAG-Kriterium: 3.3.1 Error Identification (Level A)
Komplexes Formular-Beispiel
<form method="post" aria-labelledby="form-title">
<h2 id="form-title">Kontaktformular</h2>
<!-- Feldgruppe -->
<fieldset>
<legend>Persönliche Daten</legend>
<div class="form-group">
<label for="firstname">Vorname *</label>
<input type="text" id="firstname" name="firstname"
required aria-required="true" autocomplete="given-name">
</div>
<div class="form-group">
<label for="lastname">Nachname *</label>
<input type="text" id="lastname" name="lastname"
required aria-required="true" autocomplete="family-name">
</div>
</fieldset>
<!-- Radio-Buttons -->
<fieldset>
<legend>Anrede</legend>
<div>
<input type="radio" id="herr" name="anrede" value="herr">
<label for="herr">Herr</label>
</div>
<div>
<input type="radio" id="frau" name="anrede" value="frau">
<label for="frau">Frau</label>
</div>
<div>
<input type="radio" id="divers" name="anrede" value="divers">
<label for="divers">Divers</label>
</div>
</fieldset>
<!-- Submit Button -->
<button type="submit">Absenden</button>
</form>
Best Practices:
<fieldset>+<legend>für zusammengehörige Felderautocomplete-Attribute für Autofill- Pflichtfelder mit
*undrequired - Fehlermeldungen mit
role="alert"
4. Farbkontrast & visuelle Gestaltung
Kontrastverhältnisse nach WCAG 2.1
WCAG Level AA Anforderungen:
- Normal Text (unter 18pt): Mindestens 4.5:1
- Großer Text (ab 18pt oder 14pt fett): Mindestens 3:1
- UI-Komponenten (Buttons, Icons): Mindestens 3:1
❌ Falsch (zu geringer Kontrast):
/* Kontrast nur 2.8:1 - nicht ausreichend! */
.text {
color: #999999;
background: #ffffff;
}
✅ Richtig (ausreichender Kontrast):
/* Kontrast 7.0:1 - WCAG AAA konform */
.text {
color: #333333;
background: #ffffff;
}
/* Oder: */
.text-inverted {
color: #ffffff;
background: #0066cc; /* Kontrast 4.6:1 */
}
Farbe allein reicht nicht
❌ Falsch (nur Farbe für Information):
<p style="color: red;">Fehler aufgetreten</p>
<p style="color: green;">Erfolgreich gespeichert</p>
✅ Richtig (Farbe + Icon + Text):
<p class="error">
<span aria-hidden="true">⚠️</span>
<span class="sr-only">Fehler:</span>
Fehler aufgetreten
</p>
<p class="success">
<span aria-hidden="true">✅</span>
<span class="sr-only">Erfolg:</span>
Erfolgreich gespeichert
</p>
WCAG-Kriterium: 1.4.1 Use of Color (Level A)
Testing-Tools für Kontrast
Online-Tools:
Browser-Extensions:
- WAVE (Chrome, Firefox)
- axe DevTools (Chrome, Firefox)
Command-Line:
# Pa11y für automatisierte Tests
npm install -g pa11y
pa11y https://ihre-website.de --standard WCAG2AA
5. Alternative Texte für Bilder
Bilder richtig beschreiben
❌ Falsch:
<img src="team.jpg">
<img src="logo.png" alt="Bild">
<img src="chart.png" alt="chart.png">
✅ Richtig:
<!-- Informatives Bild -->
<img src="team.jpg" alt="Unser Team von 5 Mitarbeitern im Büro bei der Arbeit">
<!-- Dekoratives Bild (kein alt-Text nötig) -->
<img src="decoration.svg" alt="" role="presentation">
<!-- Logo -->
<img src="logo.png" alt="Wendermedia - Webdesign aus Halle">
<!-- Komplexes Diagramm mit Langbeschreibung -->
<img src="sales-chart.png" alt="Umsatzentwicklung 2024"
aria-describedby="chart-description">
<div id="chart-description">
<p>Detaillierte Beschreibung: Der Umsatz stieg von 100.000€ im Januar
auf 250.000€ im Dezember 2024. Besonders stark war das Wachstum
im 3. Quartal mit +80%.</p>
</div>
Best Practices:
- Informative Bilder: Kurze Beschreibung des Inhalts/der Funktion
- Dekorative Bilder: Leeres
alt=""(nicht weglassen!) - Komplexe Grafiken:
alt+ längere Beschreibung viaaria-describedby - Icon-Buttons:
aria-labelstattalt
SVG-Icons barrierefrei
❌ Falsch:
<svg class="icon">...</svg>
✅ Richtig:
<!-- Dekoratives Icon -->
<svg class="icon" aria-hidden="true" focusable="false">...</svg>
<!-- Informatives Icon mit Label -->
<button aria-label="Suchen">
<svg aria-hidden="true" focusable="false">
<!-- Icon-Pfade -->
</svg>
</button>
<!-- SVG mit Titel und Beschreibung -->
<svg role="img" aria-labelledby="icon-title icon-desc">
<title id="icon-title">Erfolgreich</title>
<desc id="icon-desc">Grüner Haken für erfolgreiche Aktion</desc>
<!-- Icon-Pfade -->
</svg>
6. Video & Audio barrierefrei
Video mit Untertiteln und Audiodeskription
<video controls>
<source src="video.mp4" type="video/mp4">
<!-- Untertitel (Deutsch) -->
<track kind="subtitles" src="video-de.vtt" srclang="de" label="Deutsch" default>
<!-- Untertitel (Englisch) -->
<track kind="subtitles" src="video-en.vtt" srclang="en" label="English">
<!-- Audiodeskription -->
<track kind="descriptions" src="video-ad.vtt" srclang="de" label="Audiodeskription">
<!-- Fallback -->
<p>Ihr Browser unterstützt kein HTML5 Video.
<a href="video.mp4">Video herunterladen</a>
</p>
</video>
<!-- Transkript -->
<details>
<summary>Vollständiges Transkript anzeigen</summary>
<div>
<h3>Transkript: Produktvorstellung</h3>
<p><strong>0:00</strong> - Willkommen zu unserer Produktvorstellung...</p>
<p><strong>0:15</strong> - Das neue Feature ermöglicht...</p>
</div>
</details>
WCAG-Anforderungen:
- Level A: Untertitel für aufgezeichnete Videos
- Level AA: Audiodeskription oder Volltext-Alternative
- Level AAA: Gebärdensprache-Übersetzung
WebVTT-Datei Beispiel (video-de.vtt)
WEBVTT
00:00:00.000 --> 00:00:03.000
Willkommen zu unserer Produktvorstellung.
00:00:03.500 --> 00:00:07.000
Heute zeigen wir Ihnen unser neues Feature.
00:00:07.500 --> 00:00:11.000
Es ermöglicht Ihnen, Ihre Workflows zu optimieren.
7. ARIA (Accessible Rich Internet Applications)
ARIA-Grundregeln
Die 5 goldenen ARIA-Regeln:
- No ARIA is better than bad ARIA - Nutze natives HTML
- Don’t change native semantics -
<button role="link">ist falsch - All interactive ARIA controls must be keyboard accessible
- Don’t use
role="presentation"oraria-hidden="true"on focusable elements - All interactive elements must have an accessible name
ARIA Roles
<!-- Navigation -->
<nav role="navigation" aria-label="Hauptnavigation">...</nav>
<!-- Banner (Header) -->
<header role="banner">...</header>
<!-- Hauptinhalt -->
<main role="main">...</main>
<!-- Sidebar -->
<aside role="complementary" aria-label="Zusätzliche Informationen">...</aside>
<!-- Suche -->
<div role="search">
<label for="search-input">Suche</label>
<input type="search" id="search-input">
</div>
<!-- Artikelliste -->
<section role="region" aria-labelledby="blog-title">
<h2 id="blog-title">Aktuelle Blog-Artikel</h2>
<article>...</article>
</section>
ARIA States & Properties
aria-expanded (für Accordions/Dropdowns):
<button aria-expanded="false" aria-controls="menu">
Menü
</button>
<ul id="menu" hidden>
<li>Item 1</li>
<li>Item 2</li>
</ul>
<script>
button.addEventListener('click', function() {
const expanded = this.getAttribute('aria-expanded') === 'true';
this.setAttribute('aria-expanded', !expanded);
menu.hidden = expanded;
});
</script>
aria-live (für dynamische Inhalte):
<!-- Statusmeldungen -->
<div role="status" aria-live="polite" aria-atomic="true">
<!-- Wird vom Screen Reader vorgelesen, wenn sich Inhalt ändert -->
<p id="status-message"></p>
</div>
<!-- Fehlermeldungen (sofort vorlesen) -->
<div role="alert" aria-live="assertive">
<!-- Unterbricht Screen Reader sofort -->
<p id="error-message"></p>
</div>
<script>
// Status update
document.getElementById('status-message').textContent = 'Daten wurden gespeichert';
// Error
document.getElementById('error-message').textContent = 'Fehler beim Speichern!';
</script>
aria-current (für Navigation):
<nav>
<a href="/" aria-current="page">Home</a>
<a href="/blog">Blog</a>
<a href="/kontakt">Kontakt</a>
</nav>
Modal Dialog (WAI-ARIA Pattern)
<button id="open-dialog">Dialog öffnen</button>
<div role="dialog" aria-labelledby="dialog-title" aria-modal="true"
class="dialog" hidden>
<div class="dialog-content">
<h2 id="dialog-title">Bestätigung erforderlich</h2>
<p>Möchten Sie die Änderungen wirklich verwerfen?</p>
<div class="dialog-actions">
<button id="confirm">Verwerfen</button>
<button id="cancel">Abbrechen</button>
</div>
<button id="close-dialog" aria-label="Dialog schließen">×</button>
</div>
</div>
<script>
const dialog = document.querySelector('[role="dialog"]');
const openBtn = document.getElementById('open-dialog');
const closeBtn = document.getElementById('close-dialog');
const cancelBtn = document.getElementById('cancel');
// Dialog öffnen
openBtn.addEventListener('click', () => {
dialog.hidden = false;
closeBtn.focus(); // Fokus in Dialog
// Fokus-Falle (Trap focus im Dialog)
document.addEventListener('keydown', trapFocus);
});
// Dialog schließen
function closeDialog() {
dialog.hidden = true;
openBtn.focus(); // Fokus zurück zum Trigger
document.removeEventListener('keydown', trapFocus);
}
closeBtn.addEventListener('click', closeDialog);
cancelBtn.addEventListener('click', closeDialog);
// Escape-Taste
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape' && !dialog.hidden) {
closeDialog();
}
});
// Fokus-Falle im Dialog
function trapFocus(e) {
if (e.key !== 'Tab') return;
const focusableElements = dialog.querySelectorAll(
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
);
const firstElement = focusableElements[0];
const lastElement = focusableElements[focusableElements.length - 1];
if (e.shiftKey && document.activeElement === firstElement) {
lastElement.focus();
e.preventDefault();
} else if (!e.shiftKey && document.activeElement === lastElement) {
firstElement.focus();
e.preventDefault();
}
}
</script>
8. Responsive & Zoom-fähig
Responsives Design (WCAG 2.1)
WCAG-Kriterium: 1.4.10 Reflow (Level AA)
Inhalte müssen bei 320px Breite und 256px Höhe (entspricht 400% Zoom) ohne horizontales Scrollen lesbar sein.
❌ Falsch (fixed width):
.container {
width: 1200px; /* Bricht bei kleinen Viewports */
}
✅ Richtig (fluid width):
.container {
max-width: 1200px;
width: 100%;
padding: 0 20px;
margin: 0 auto;
}
/* Mobile First */
@media (min-width: 768px) {
.container {
padding: 0 40px;
}
}
Text-Skalierung
WCAG-Kriterium: 1.4.4 Resize Text (Level AA)
Text muss bis 200% vergrößerbar sein ohne Funktionsverlust.
❌ Falsch (px-basiert, nicht skalierbar):
body {
font-size: 16px; /* Skaliert nicht mit Browser-Einstellungen */
}
✅ Richtig (rem-basiert):
/* Root Font Size (1rem = 16px bei Standard-Einstellung) */
html {
font-size: 100%; /* Respektiert User-Einstellungen */
}
body {
font-size: 1rem; /* 16px */
line-height: 1.5; /* Mindestens 1.5 für Lesbarkeit */
}
h1 {
font-size: 2.5rem; /* 40px */
line-height: 1.2;
}
p {
font-size: 1rem;
margin-bottom: 1.5rem;
}
/* Minimum Font Size */
small {
font-size: 0.875rem; /* Nicht kleiner als 14px */
}
Zeilenabstand & Zeichenabstand (WCAG 1.4.12):
p {
line-height: 1.5; /* Mindestens 1.5x Schriftgröße */
letter-spacing: 0.12em; /* Optional für bessere Lesbarkeit */
word-spacing: 0.16em;
}
9. Testing & Qualitätssicherung
Automatisierte Tests
1. axe DevTools (Browser-Extension)
Installation: Chrome Web Store / Firefox Add-ons
# Oder: Command Line
npm install -g @axe-core/cli
axe https://ihre-website.de --tags wcag2aa
2. Lighthouse (in Chrome DevTools)
# Command Line
npm install -g lighthouse
lighthouse https://ihre-website.de --only-categories=accessibility --view
3. Pa11y (CI/CD Integration)
npm install -g pa11y
pa11y https://ihre-website.de --standard WCAG2AA --reporter json > report.json
4. Jest + jest-axe (Unit Tests)
// setup-tests.js
import { toHaveNoViolations } from 'jest-axe';
expect.extend(toHaveNoViolations);
// component.test.js
import { render } from '@testing-library/react';
import { axe } from 'jest-axe';
import MyComponent from './MyComponent';
test('should have no accessibility violations', async () => {
const { container } = render(<MyComponent />);
const results = await axe(container);
expect(results).toHaveNoViolations();
});
Manuelle Tests
Tastatur-Navigation:
- Tab durch alle interaktiven Elemente
- Prüfen: Fokus sichtbar? Logische Reihenfolge?
- Enter/Space auf Buttons testen
- Escape schließt Modals?
Screen Reader Tests:
NVDA (Windows - kostenlos):
1. NVDA starten (Strg + Alt + N)
2. Website öffnen
3. Mit Pfeil-Tasten durch Inhalte navigieren
4. H-Taste: Überschriften-Navigation
5. K-Taste: Links-Navigation
6. F-Taste: Formular-Navigation
VoiceOver (macOS - integriert):
1. VoiceOver aktivieren (Cmd + F5)
2. Rotor öffnen (Ctrl + Option + U)
3. Landmarks, Überschriften, Links testen
4. VO + Pfeiltasten: Navigation
Checkliste für manuelle Tests:
- Alle Bilder haben alt-Text (oder alt="")
- Überschriften in korrekter Reihenfolge (h1 → h2 → h3)
- Fokus-Reihenfolge logisch
- Fokus deutlich sichtbar
- Alle Funktionen per Tastatur bedienbar
- Formulare haben Labels
- Fehlermeldungen verständlich
- Farbkontrast ausreichend (4.5:1)
- Text bis 200% vergrößerbar
- Kein horizontales Scrollen bei 320px Breite
- Videos haben Untertitel
- Skip-Link vorhanden
Browser-Testing
Mindestens testen mit:
- Chrome + Screen Reader
- Firefox + Screen Reader
- Safari + VoiceOver (macOS/iOS)
- Edge + Narrator (Windows)
10. Entwickler-Workflow für BFSG-Konformität
Pre-Commit Hook für Accessibility
.git/hooks/pre-commit:
#!/bin/sh
echo "Running accessibility tests..."
# Pa11y für lokale HTML-Dateien
npm run test:a11y
if [ $? -ne 0 ]; then
echo "❌ Accessibility tests failed. Commit aborted."
exit 1
fi
echo "✅ Accessibility tests passed."
package.json:
{
"scripts": {
"test:a11y": "pa11y-ci --config .pa11yci.json",
"test:a11y:report": "pa11y https://localhost:3000 --reporter html > a11y-report.html"
},
"devDependencies": {
"pa11y": "^7.0.0",
"pa11y-ci": "^3.0.1"
}
}
.pa11yci.json:
{
"defaults": {
"standard": "WCAG2AA",
"timeout": 10000,
"wait": 500
},
"urls": [
"http://localhost:3000/",
"http://localhost:3000/blog",
"http://localhost:3000/kontakt"
]
}
Continuous Integration (GitHub Actions)
.github/workflows/accessibility.yml:
name: Accessibility Tests
on: [push, pull_request]
jobs:
a11y:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node
uses: actions/setup-node@v3
with:
node-version: '18'
- name: Install dependencies
run: npm ci
- name: Build site
run: npm run build
- name: Start server
run: npm run preview &
- name: Wait for server
run: npx wait-on http://localhost:4173
- name: Run Pa11y
run: npm run test:a11y
- name: Run axe
run: npx @axe-core/cli http://localhost:4173 --tags wcag2aa
VS Code Extensions für Accessibility
Empfohlene Extensions:
- axe Accessibility Linter: Echtzeit-Warnungen im Code
- webhint: HTML/CSS/Accessibility Linting
- HTMLHint: HTML-Validierung
- Stylelint: CSS-Linting mit a11y-Regeln
.vscode/extensions.json:
{
"recommendations": [
"deque-systems.vscode-axe-linter",
"webhint.vscode-webhint",
"htmlhint.vscode-htmlhint"
]
}
Budget & Zeitaufwand
Neues Projekt (von Anfang an barrierefrei)
| Phase | Aufwand | Kosten |
|---|---|---|
| Planung & Konzeption | +10% | +800€ |
| Design (Kontraste, Fokus-Stile) | +15% | +1.200€ |
| Entwicklung (semantisches HTML, ARIA) | +20% | +2.500€ |
| Testing & QA | +40% | +2.000€ |
| Gesamt Mehraufwand | +20-25% | +6.500€ |
Wichtig: Bei Planung von Anfang an ist der Mehraufwand minimal (20-25%). Nachträgliche Anpassungen kosten 3-5x mehr.
Bestehendes Projekt nachrüsten
| Komplexität | Aufwand | Kosten |
|---|---|---|
| Kleine Website (5-10 Seiten) | 40-60h | 4.000€ - 6.000€ |
| Mittlere Website (20-50 Seiten) | 80-120h | 8.000€ - 12.000€ |
| Große Website/Shop (100+ Seiten) | 200-400h | 20.000€ - 40.000€ |
| Web-App (komplex) | 400-800h | 40.000€ - 80.000€ |
Kostentreiber:
- Komplexe JavaScript-Interaktionen (Dropdown-Menüs, Modals, Carousels)
- Video-Inhalte (Untertitel, Transkripte erstellen)
- Dynamische Formulare mit Custom-Komponenten
- Legacy-Code ohne semantisches HTML
Häufige Fehler & Quick Wins
Top 10 Accessibility-Fehler
-
Fehlende alt-Texte bei Bildern (90% aller Websites)
- Fix:
<img alt="Beschreibung">
- Fix:
-
Unzureichender Farbkontrast (85%)
- Fix: WebAIM Contrast Checker nutzen
-
Fehlende Form-Labels (70%)
- Fix:
<label for="input-id">
- Fix:
-
Nicht-tastaturzugängliche Elemente (65%)
- Fix:
<button>statt<div onclick>
- Fix:
-
Überschriften-Hierarchie falsch (60%)
- Fix: h1 → h2 → h3 (keine Sprünge)
-
Links ohne aussagekräftigen Text (55%)
- Fix: “Mehr erfahren” → “Mehr über BFSG erfahren”
-
Fehlende ARIA-Labels bei Icons (50%)
- Fix:
<button aria-label="Suchen">
- Fix:
-
Videos ohne Untertitel (85%)
- Fix: WebVTT-Dateien erstellen
-
Fokus-Indikator entfernt (40%)
- Fix: NIEMALS
outline: noneohne Alternative
- Fix: NIEMALS
-
Leere Links/Buttons (35%)
- Fix: Sichtbarer Text oder
aria-label
- Fix: Sichtbarer Text oder
Quick Wins (unter 1 Stunde)
✅ Alt-Texte ergänzen:
# Alle Bilder ohne alt finden
grep -r "<img" . | grep -v "alt="
✅ Skip-Link hinzufügen (5 Minuten):
<a href="#main" class="skip-link">Zum Hauptinhalt</a>
✅ Semantic HTML (30 Minuten):
- Ersetze
<div class="header">→<header> - Ersetze
<div class="nav">→<nav> - Ersetze
<div class="main">→<main>
✅ Fokus-Styles (10 Minuten):
:focus-visible {
outline: 3px solid #0066cc;
outline-offset: 2px;
}
Ressourcen & Weiterführendes
Offizielle Standards
Testing-Tools
Automatisiert:
Manuell:
- NVDA Screen Reader (Windows, kostenlos)
- JAWS Screen Reader (Windows, kostenpflichtig)
- VoiceOver (macOS/iOS, integriert)
Kontrast-Checker:
Checklisten
Fazit: BFSG-Konformität ist machbar
Die technische Umsetzung des BFSG erfordert systematisches Vorgehen, aber keine Raketenwissenschaft:
Die 5 Kern-Prinzipien
- Semantisches HTML - Nutze
<header>,<nav>,<main>,<button> - Tastaturnavigation - Alles muss ohne Maus bedienbar sein
- Alternative Texte - Beschreibe alle visuellen Inhalte
- Ausreichender Kontrast - Mindestens 4.5:1 für Text
- Testen, testen, testen - Automatisiert + manuell mit Screen Reader
Ihr Weg zur BFSG-Konformität
Bis 28. Juni 2025 müssen Sie handeln:
- Phase 1 (Jetzt - Januar 2025): Ist-Analyse mit automatisierten Tools
- Phase 2 (Februar - März 2025): Quick Wins umsetzen (alt-Texte, Kontraste, Semantik)
- Phase 3 (April - Mai 2025): Komplexe Anpassungen (ARIA, Formulare, Videos)
- Phase 4 (Juni 2025): Testing & Dokumentation
Benötigen Sie Unterstützung?
Wendermedia ist BFSG-spezialisiert und unterstützt Sie bei der technischen Umsetzung:
Unsere BFSG-Services
✅ BFSG Compliance Audit (980€)
- Automatisierte Tests (axe, Pa11y, Lighthouse)
- Manuelle Screen Reader Tests
- Detaillierter Report mit Handlungsempfehlungen
- Priorisierte To-Do-Liste
✅ BFSG Technische Umsetzung (ab 4.000€)
- Semantisches HTML-Refactoring
- ARIA-Integration
- Tastaturnavigation optimieren
- Kontrast-Anpassungen
- Testing & Dokumentation
✅ BFSG Entwickler-Schulung (1.200€/Tag)
- Team-Workshop (4-8h)
- Best Practices & Code-Reviews
- Testing-Workflows einrichten
- Laufender Support
Jetzt BFSG-Audit anfragen
Deadline 28. Juni 2025 - Handeln Sie jetzt!
📞 Kostenlose BFSG-Erstberatung buchen
Oder rufen Sie direkt an: +49 345 2470 0940
Autor: Arnold Wender, Webdesign & BFSG-Spezialist aus Halle (Saale)
Letzte Aktualisierung: November 2025