Color Contrast Checker
WCAG-AA- und AAA-Kontrastverhältnis zwischen Vorder- und Hintergrundfarbe prüfen
Vordergrundfarbe (Text)
Hintergrundfarbe
Großtextbeispiel (18px fett)
Normaltextbeispiel — so sieht der Fließtext gegen die gewählte Hintergrundfarbe aus.
Kontrastverhältnis
14.63:1
WCAG-Konformität
Bestanden
Normal AA
Bestanden
Normal AAA
Bestanden
Groß AA
Bestanden
Groß AAA
WCAG AA — Normaltext: 4.5:1, Großtext (18px+ oder 14px fett): 3:1
WCAG AAA — Normaltext: 7:1, Großtext (18px+ oder 14px fett): 4.5:1
Was ist Farbkontrastprüfung?
Farbkontrastprüfung misst den Luminanzunterschied zwischen einer Vordergrundfarbe (typischerweise Text) und einer Hintergrundfarbe und drückt das Ergebnis als Verhältnis aus. Ein Verhältnis von 1:1 bedeutet, dass die Farben identisch sind; 21:1 ist das Maximum und steht für Schwarz auf Weiß oder umgekehrt. Die Web Content Accessibility Guidelines (WCAG) des W3C legen Mindestkontrastverhältnisse fest, die Text erfüllen muss, damit Menschen mit eingeschränktem Sehvermögen oder Farbfehlsichtigkeit ihn lesen können.
Die Kontrastverhältnisformel stammt aus WCAG 2.x und basiert auf relativer Luminanz — einem Maß dafür, wie hell eine Farbe dem menschlichen Auge erscheint. Relative Luminanz wird berechnet, indem jeder sRGB-Kanal linearisiert (Gamma entfernt) und nach den ITU-R BT.709-Koeffizienten gewichtet wird: 0,2126 für Rot, 0,7152 für Grün und 0,0722 für Blau. Grün trägt am meisten bei, weil das menschliche Auge am empfindlichsten auf grünes Licht reagiert. Das Verhältnis ergibt sich dann aus (L1 + 0,05) / (L2 + 0,05), wobei L1 die Luminanz der helleren Farbe ist.
WCAG definiert zwei Konformitätsstufen. Stufe AA erfordert ein Kontrastverhältnis von mindestens 4,5:1 für normalen Text und 3:1 für Großtext (18px oder mehr, oder 14px fett). Stufe AAA erhöht die Anforderungen auf 7:1 bzw. 4,5:1. WCAG 2.1 führte außerdem Erfolgskriterium 1.4.11 ein, das ein 3:1-Verhältnis für Nicht-Text-UI-Komponenten wie Rahmen, Icons und Fokusindikatoren vorschreibt.
Warum diesen Contrast Checker verwenden?
Kontrast mit dem Auge zu beurteilen ist unzuverlässig. Farben, die auf einem kalibrierten Monitor deutlich unterschiedlich wirken, können auf einem minderwertigen Laptop-Display, im direkten Sonnenlicht oder für Menschen mit Deuteranopie verschwimmen. Ein numerisches Verhältnis beseitigt das Rätselraten und liefert ein eindeutiges Bestanden/Nicht-bestanden-Urteil gegenüber dem WCAG-Standard.
Anwendungsfälle für den Contrast Checker
WCAG-Kontrastverhältnisanforderungen
Die folgende Tabelle fasst die von WCAG 2.1 geforderten Mindestkontrastverhältnisse für verschiedene Inhaltstypen und Konformitätsstufen zusammen. Großtext ist definiert als 18px (24 CSS-Pixel) oder mehr bei normalem Gewicht, oder 14px (18,66 CSS-Pixel) oder mehr bei fettem Gewicht.
| Stufe | Mindestverhältnis | Gilt für | Hinweis |
|---|---|---|---|
| AA Normal text | 4.5 : 1 | Body text, paragraphs, labels | Minimum for most UI text |
| AA Large text | 3.0 : 1 | Text >= 18px, or >= 14px bold | Minimum for headings |
| AA UI components | 3.0 : 1 | Borders, icons, focus indicators | Non-text contrast (WCAG 1.4.11) |
| AAA Normal text | 7.0 : 1 | Body text at highest standard | Enhanced readability |
| AAA Large text | 4.5 : 1 | Large text at highest standard | Enhanced for headings |
Luminanz, AA und AAA erklärt
Die Kontrastverhältnisberechnung hat drei Stufen: Luminanz für jede Farbe berechnen, das Verhältnis ableiten und mit den WCAG-Schwellenwerten vergleichen.
Code-Beispiele
WCAG-Kontrastverhältnisse programmatisch berechnen. Jedes Beispiel implementiert die relative Luminanzformel aus WCAG 2.x und die Kontrastverhältnisberechnung. Die gleichen Schwarz-auf-Weiß- und Indigo-auf-Weiß-Paare werden zum Vergleich getestet.
// Calculate relative luminance per WCAG 2.x (sRGB)
function luminance(r, g, b) {
const [rs, gs, bs] = [r, g, b].map(c => {
c /= 255
return c <= 0.04045 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4)
})
return 0.2126 * rs + 0.7152 * gs + 0.0722 * bs
}
// Contrast ratio between two RGB colors
function contrastRatio(fg, bg) {
const l1 = luminance(...fg)
const l2 = luminance(...bg)
const lighter = Math.max(l1, l2)
const darker = Math.min(l1, l2)
return (lighter + 0.05) / (darker + 0.05)
}
contrastRatio([0, 0, 0], [255, 255, 255]) // -> 21.0
contrastRatio([99, 102, 241], [255, 255, 255]) // -> 3.95
contrastRatio([29, 78, 216], [255, 255, 255]) // -> 6.06 (AA pass)def luminance(r: int, g: int, b: int) -> float:
"""Relative luminance per WCAG 2.x, ITU-R BT.709 coefficients."""
channels = []
for c in (r, g, b):
c /= 255
channels.append(c / 12.92 if c <= 0.04045 else ((c + 0.055) / 1.055) ** 2.4)
return 0.2126 * channels[0] + 0.7152 * channels[1] + 0.0722 * channels[2]
def contrast_ratio(fg: tuple, bg: tuple) -> float:
l1 = luminance(*fg)
l2 = luminance(*bg)
lighter, darker = max(l1, l2), min(l1, l2)
return (lighter + 0.05) / (darker + 0.05)
print(f"{contrast_ratio((0, 0, 0), (255, 255, 255)):.2f}") # -> 21.00
print(f"{contrast_ratio((99, 102, 241), (255, 255, 255)):.2f}") # -> 3.95
# Check WCAG AA for normal text
ratio = contrast_ratio((29, 78, 216), (255, 255, 255))
print(f"{ratio:.2f} — {'AA pass' if ratio >= 4.5 else 'AA fail'}") # -> 6.06 — AA passpackage main
import (
"fmt"
"math"
)
func linearize(c float64) float64 {
c /= 255
if c <= 0.04045 {
return c / 12.92
}
return math.Pow((c+0.055)/1.055, 2.4)
}
func luminance(r, g, b int) float64 {
return 0.2126*linearize(float64(r)) +
0.7152*linearize(float64(g)) +
0.0722*linearize(float64(b))
}
func contrastRatio(fgR, fgG, fgB, bgR, bgG, bgB int) float64 {
l1 := luminance(fgR, fgG, fgB)
l2 := luminance(bgR, bgG, bgB)
lighter := math.Max(l1, l2)
darker := math.Min(l1, l2)
return (lighter + 0.05) / (darker + 0.05)
}
func main() {
ratio := contrastRatio(0, 0, 0, 255, 255, 255)
fmt.Printf("%.2f\n", ratio) // -> 21.00
ratio = contrastRatio(29, 78, 216, 255, 255, 255)
fmt.Printf("%.2f\n", ratio) // -> 6.06 (AA pass for normal text)
}/* WCAG-safe color pairs — tested contrast ratios */
/* 12.63:1 — passes AAA normal text */
.high-contrast {
color: #1e293b; /* slate-800 */
background: #f8fafc; /* slate-50 */
}
/* 7.07:1 — passes AAA normal text */
.dark-theme-text {
color: #e2e8f0; /* slate-200 */
background: #0f172a; /* slate-900 */
}
/* 4.57:1 — passes AA normal, fails AAA */
.accent-on-white {
color: #1d4ed8; /* blue-700 */
background: #ffffff;
}
/* 2.14:1 — fails AA for text, but passes 3:1 for large text */
.muted-heading {
color: #94a3b8; /* slate-400 */
background: #ffffff;
}