WCAG-Farbkontrast erreichen, ohne zu raten
Für normalen Fließtext verlangt WCAG-Stufe AA ein Kontrastverhältnis von mindestens 4,5:1 gegenüber dem Hintergrund. Großer Text braucht 3:1. Interface-Komponenten und bedeutungstragende Grafiken brauchen 3:1. Stufe AAA hebt Text auf 7:1 und großen Text auf 4,5:1. Die Verhältnisse reichen von 1:1 (identische Farben) bis 21:1 (reines Schwarz auf reinem Weiß).
Mit dem Auge lässt sich das nicht beurteilen. Zwei Paare, die auf deinem Monitor ähnlich gut lesbar wirken, können auf entgegengesetzten Seiten der Schwelle liegen; das Verhältnis muss also berechnet werden.
Die Schwellenwerte
| Worum es geht | AA | AAA |
|---|---|---|
| Normaler Text | 4,5:1 | 7:1 |
| Großer Text | 3:1 | 4,5:1 |
| Interface-Komponenten und grafische Objekte | 3:1 | keine höhere Anforderung |
Sie stammen aus drei Erfolgskriterien: 1.4.3 Kontrast (Minimum) auf AA, 1.4.6 Kontrast (erhöht) auf AAA und 1.4.11 Nicht-Text-Kontrast auf AA, das die sichtbaren Begrenzungen von Bedienelementen und diejenigen Teile von Grafiken abdeckt, die du zum Verstehen brauchst.
Großer Text bedeutet mindestens 18 Punkt oder 14 Punkt in Fett, was ungefähr 24px normal oder etwa 18,5px fett entspricht. Es bedeutet nicht „eine Überschrift“: Eine 20px große Überschrift ist im Sinne der Regeln normaler Text und braucht die vollen 4,5:1.
Ein paar Dinge sind ausgenommen: rein dekorativer Text, Text in einem inaktiven Bedienelement, Text, der Teil eines Bildes mit anderem wesentlichem visuellem Inhalt ist, und Wortmarken. Platzhalter- und Hilfetext sind nicht ausgenommen.
Was das Verhältnis tatsächlich misst
Die Formel vergleicht die relative Leuchtdichte der beiden Farben:
ratio = (L_lighter + 0.05) / (L_darker + 0.05)
Die relative Leuchtdichte ist eine Zahl von 0 (Schwarz) bis 1 (Weiß) und steht dafür, wie viel Licht eine Farbe abgibt. Sie wird berechnet, indem die sRGB-Gammakurve auf jedem Kanal rückgängig gemacht und die Kanäle anschließend gewichtet werden:
L = 0.2126 R + 0.7152 G + 0.0722 B (on linearised channels)
Die 0.05, die auf beiden Seiten addiert wird, bildet ein wenig Umgebungslicht ab, das vom Bildschirm zurückgeworfen wird; deshalb liegt das Maximum bei 21 und nicht bei unendlich.
Daraus folgen zwei Dinge. Das Verhältnis hängt nur von der Leuchtdichte ab, nicht vom Farbton, zwei Farben können sich also im Farbton völlig unterscheiden und trotzdem voreinander nahezu unsichtbar sein. Und es ist symmetrisch, es spielt also keine Rolle, welche Farbe du Vordergrund nennst.
Relative Leuchtdichte ist nicht Helligkeit
Sieh dir diese Gewichte an. Grün trägt etwa 72 % zur Leuchtdichte bei, Rot etwa 21 % und Blau knapp 7 %. Das ist ein Modell des menschlichen Sehens, nicht davon, wie kräftig eine Farbe wirkt, und es liefert Ergebnisse, die sich falsch anfühlen, bis du dich daran gewöhnt hast.
- Reines Gelb
#FFFF00auf Weiß liegt bei etwa 1,07:1, also fast unsichtbar, obwohl Gelb wie eine kräftige Farbe wirkt. - Dasselbe Gelb auf Schwarz liegt bei etwa 19,6:1, fast so hoch wie Weiß auf Schwarz.
- Reines Blau
#0000FFauf Schwarz liegt bei etwa 2,4:1 und fällt überall durch, obwohl es kräftig und gesättigt aussieht.
Deshalb ist auch die Helligkeit in HSL ein schlechter Ersatzwert. Zwei Farben können beide bei 50 % Helligkeit in HSL liegen und sehr unterschiedliche Leuchtdichten haben, denn HSL behandelt Farbton und Helligkeit als unabhängig, das Sehen tut das nicht. Rechne um und miss dann, statt anzunehmen, ein Helligkeitsschritt sei ein Kontrastschritt.
Die Fehler, die immer wieder passieren
Grauer Fließtext auf Weiß. Das ist der große Klassiker. Das hellste Grau, das auf Weiß AA besteht, ist etwa #767676 und kommt auf 4,54:1. Eine Stufe heller, #777777, ergibt 4,48:1 und fällt durch. Beliebte „gedämpfte“ Grautöne wie #999999 landen bei etwa 2,9:1, weniger als zwei Drittel der Anforderung. Wenn du auf Weiß AAA willst, brauchst du ungefähr #595959, was genau 7:1 ergibt.
Platzhalter- und Hilfetext. Sie werden mehrere Stufen heller gesetzt als Fließtext, weil sie zweitrangig sind. Sie sind trotzdem Text und brauchen trotzdem 4,5:1.
Halbtransparente Farben. Ein Verhältnis, das aus der deklarierten Farbe berechnet wurde, ist bedeutungslos, wenn das Element bei 60 % Deckkraft liegt. Ermittle die zusammengesetzte Farbe, die tatsächlich auf dem Bildschirm erscheint, und miss diese.
Text über Bildern, Verläufen und Video. Das Verhältnis ändert sich von Pixel zu Pixel, und entscheidend ist das schlechteste Pixel. Die übliche Lösung ist eine abdunkelnde Fläche hinter dem Text, statt zu hoffen, dass das Foto dunkel bleibt.
Buttons in der Markenfarbe. Weißer Text auf einer mitteltonigen Markenfarbe landet sehr oft zwischen 3:1 und 4,5:1, besteht also als grafisches Objekt und fällt als Beschriftung durch. Dunkle den Button ab, oder nimm den Verstoß bewusst in Kauf.
Fokusanzeigen und Buttons, die nur aus einem Icon bestehen. Beide fallen unter die 3:1-Regel für Nicht-Text. Ein Fokusring in einem leicht anderen Ton derselben Farbe ist ein häufiger Fehlgriff, ebenso ein graues Icon, das der einzige Inhalt eines Buttons ist.
Dark Mode durch Umkehrung. Eine helle Palette umzudrehen erhält die Verhältnisse nicht, denn die Leuchtdichte ist nicht symmetrisch um die Mitte. Reines Weiß auf reinem Schwarz ergibt das Maximum von 21:1, aber viele Menschen empfinden das Nachleuchten als unangenehm, ein gebrochenes Weiß auf einem sehr dunklen Grau, etwa #E6E6E6 auf #121212 mit rund 15:1, ist deshalb ein verbreiteter Kompromiss.
Aus einem Screenshot messen. Eine Pipette am Rand von kantengeglättetem Text greift eine Mischung aus Text und Hintergrund ab, nicht die Textfarbe. Miss in der Mitte eines dicken Strichs, oder besser, lies die Werte aus deinem CSS.
Ein Arbeitsablauf, der ohne Raten auskommt
Lege zuerst den Hintergrund fest, dunkle oder helle dann den Vordergrund so weit ab, bis er die Schwelle mit etwas Reserve überschreitet, und halte dieses Paar fest. Baue die Palette aus freigegebenen Paaren statt aus freigegebenen Farben: Eine Farbe ist nicht für sich allein barrierefrei, sondern nur in Kombination. Prüfe auch jeden Zustand, nicht nur den Ruhezustand, und beide Themes, wenn du einen Dark Mode auslieferst.
Ein letzter Hinweis. Ein neueres wahrnehmungsbasiertes Modell, APCA, wird für eine künftige WCAG-Version entwickelt und verhält sich deutlich anders, besonders bei hellem Text auf dunklem Hintergrund. Es lohnt sich, davon zu wissen, aber die Zahlen, die heute einzuhalten sind, sind die WCAG-2-Verhältnisse von oben.