2 Punkte von GN⁺ 2025-05-19 | 1 Kommentare | Auf WhatsApp teilen
  • Mit der Funktion contrast-color() kann der Browser bei verschiedenen Hintergrundfarben, etwa für Buttons, automatisch eine schwarze oder weiße Schriftfarbe auswählen.
  • Auch in großen Projekten wird es dadurch einfacher, die Lesbarkeit von Text zu erhalten, und die Wartung wird effizienter.
  • In der Safari Technology Preview wird derzeit der offizielle Algorithmus aus WCAG 2 verwendet, der jedoch von der tatsächlichen menschlichen Wahrnehmung abweichen kann.
  • Im Zuge der Entwicklung von WCAG 3 wird über die Einführung des Algorithmus der nächsten Generation, APCA, diskutiert, der eine bessere Bewertung von Helligkeitskontrasten verspricht.
  • Über den einfachen Schwarz-Weiß-Kontrast hinaus werden künftig voraussichtlich weitere Farboptionen und Funktionen zur Verbesserung der Barrierefreiheit hinzukommen.

Überblick und Hintergrund zur Einführung von contrast-color()

  • In Designs mit vielen Buttons oder Interface-Komponenten in unterschiedlichen Hintergrundfarben ist die Lesbarkeit der Schriftfarbe (Textfarbe) entscheidend.
  • Bisher mussten Entwickler Hintergrund- und Textfarben jeweils manuell passend kombinieren, doch in großen Projekten steigt dadurch das Risiko von Komplexität in der Verwaltung und Fehlern.
  • Mit der CSS-Funktion contrast-color() muss der Entwickler nur noch die Hintergrundfarbe festlegen, und der Browser wählt automatisch zwischen schwarzer oder weißer Schriftfarbe die mit dem höheren Kontrast aus.
  • Dadurch werden Wartung und Effizienz der Designarbeit deutlich verbessert.
  • Verwendet wird sie ganz einfach mit einer Deklaration wie color: contrast-color(Farbe);.

Beispiel zur Verwendung von contrast-color()

  • Weist man der Hintergrundfarben-Variable eines Buttons eine gewünschte Farbe zu, wird die Textfarbe mit contrast-color() automatisch als kontrastierendes Schwarz oder Weiß gewählt.
  • Da jeweils nur eine Farbe verwaltet werden muss, wird die maintenance bei Änderungen der Designrichtlinien oder bei der Unterstützung von Dark/Light Mode einfacher.
button {
  background-color: var(--button-color);
  color: contrast-color(var(--button-color));
}
  • Mit der Relative Color Syntax lassen sich auch für den Hover-Zustand Hintergrund- und Textfarben konsistent verwalten.

Aspekte der Barrierefreiheit und Erklärung des Algorithmus

  • Der Einsatz von contrast-color() löst nicht automatisch alle Barrierefreiheitsprobleme (Accessibility).
  • Bei bestimmten Hintergrundfarben mittlerer Helligkeit kann es vorkommen, dass weder Schwarz noch Weiß die erforderlichen Kriterien erfüllt.
  • Der derzeit in der Safari Technology Preview verwendete WCAG-2-Algorithmus ist der offizielle Standard für Web-Barrierefreiheit.
    • Er trifft die Auswahl auf Basis des Kontrastverhältnisses, liefert aber manchmal Ergebnisse, die nicht mit dem tatsächlich wahrgenommenen Helligkeitskontrast übereinstimmen.
  • Ein Beispiel: Auf einem blauen Hintergrund mit #317CFF wird rechnerisch Schwarz als kontrastreicher bewertet, obwohl Weiß in der Praxis besser lesbar ist.
  • Als Reaktion auf diese Kritik und den Wunsch nach Verbesserungen wird im Barrierefreiheitsstandard der nächsten Generation (WCAG 3) über die Einführung von APCA (Accessible Perceptual Contrast Algorithm) diskutiert.
  • APCA berechnet Farbkontraste unter Berücksichtigung menschlicher Wahrnehmungseigenschaften und kann dadurch die tatsächliche Lesbarkeit besser absichern.

In realen Umgebungen ausreichend Kontrast sicherstellen

  • Mit der CSS-Media-Query @media (prefers-contrast: more) lassen sich zusätzliche Stile mit hohem Kontrast abhängig von den Barrierefreiheitspräferenzen der Nutzer anwenden.
@media (prefers-contrast: more) {
  /* Stil mit höherem Kontrast definieren */
}
  • Wenn die zentrale Markenfarbe zum Beispiel ein helles Grün wie #2DAD4E ist, könnte contrast-color() künftig zwar Weiß auswählen, doch für kleinen Text wäre der Kontrast möglicherweise weiterhin nicht ausreichend.
  • Mit dem APCA-Algorithmus lassen sich die erforderlichen Mindestkontrastwerte je nach Schriftgröße und -stärke genauer beurteilen, was praktische Designentscheidungen unterstützt.
    • Für Text mit 24px und Schriftschnitt 400 ist Weiß in der Praxis passend, bei dünneren FONTs oder kleinerem Text wird jedoch ein dunklerer Hintergrund empfohlen.
  • Designteams können Farbpaletten für Bedingungen wie Light/Dark Mode oder prefers-contrast bequem per Variablen verwalten.
--button-color: #2DAD4E;

@media (prefers-contrast: more) {
  @media (prefers-color-scheme: light) {
    --button-color: #419543;
  }
  @media (prefers-color-scheme: dark) {
    --button-color: #77CA8B;
  }
}
button {
  background-color: var(--button-color);
  color: contrast-color(var(--button-color));
  font-size: 1.5rem;
  font-weight: 500;
}
  • Im Kern bedeutet contrast-color(), dass nur noch die Hintergrundfarbe verwaltet werden muss, während der Browser das passende Textfarbenpaar mit ausreichendem Kontrast automatisch erzeugt.

Über Schwarz und Weiß hinaus

  • Die aktuelle Version von contrast-color() wählt nur zwischen Schwarz und Weiß, doch frühe Versionen konnten auch aus mehreren Farben auswählen.
  • Die CSS Working Group stellt zunächst bewusst die einfache Version bereit, um künftige Algorithmusänderungen und Kompatibilität besser zu berücksichtigen; später sind Erweiterungen wie benutzerdefinierte Farboptionen oder die Angabe eines gewünschten Mindestkontrasts geplant.
  • Für einfache Anforderungen ist die Funktion schon jetzt sehr nützlich.
  • Sie kann nicht nur für Hintergrundfarben, sondern auch für Rahmen und andere visuelle Elemente vielseitig eingesetzt werden.

Fazit und weiterführende Hinweise

  • Sobald der Barrierefreiheitsstandard der nächsten Generation berücksichtigt wird, wird contrast-color() durch Austausch des Algorithmus eine bessere automatische Kontrastauswahl unterstützen.
  • Bis dahin ist die Funktion besonders nützlich, wenn die zentrale Hintergrundfarbe klar hell oder dunkel ist.
  • Sie lässt sich breit auch auf verschiedenste UI-Elemente anwenden, nicht nur auf Text.
  • Es ist sinnvoll, aktuelle Barrierefreiheitsalgorithmen wie APCA (Accessible Perceptual Contrast Algorithm) weiter im Blick zu behalten.

Referenzen

  • In der offiziellen Dokumentation zu APCA und im APCA Contrast Calculator lassen sich verschiedene Beispiele und Bewertungskriterien nachsehen.
  • Die Standardisierungsdiskussion zur Funktion contrast-color in der CSSWG läuft weiter.
  • In WebKit und den zugehörigen Communities können Meinungen geteilt und Feedback eingebracht werden.

1 Kommentare

 
GN⁺ 2025-05-19
Hacker-News-Kommentare
  • Um dieses Problem zu lösen, arbeite ich an einem Tool zum Erstellen von Paletten, bei denen Farbpaarungen bereits in der Entwurfsphase einfache und vorhersagbare WCAG-/APCA-Kontrastverhältnisse haben. Auf https://www.inclusivecolors.com/ gibt es auf dem Desktop mehr Funktionen. Ein Ansatz ist, Farbfelder in Abstufungen von 100 (hell) bis 900 (dunkel) zu erzeugen und die Helligkeit so anzupassen, dass z. B. eine Farbe der Stufe 700 einen klaren Kontrast zu Stufe 100 hat und 800 zu 200. So weiß man, dass Kombinationen wie red-700 vs gray-100 oder green-800 vs yellow-200 zuverlässig Kontrast bieten, ohne die Helligkeit jedes Mal prüfen zu müssen. Im Menü Contrast kann man untersuchen, wie viel strenger der APCA-Algorithmus im Vergleich zu WCAG ist, besonders bei dunkler Schrift auf hellem Hintergrund. Das ist der Grund, warum man WCAG nicht für dunkle Themes verwenden sollte. In den Beispielen mit den Paletten von Tailwind und IBM Carbon sieht man, dass sich Sättigung und Farbton (Hue) pro Stufe nichtlinear verändern. Deshalb ist es zwar einfach, nur zwischen Schwarz und Weiß mit optimalem Kontrast zu wählen, aber für Paletten, bei denen Branding wichtig ist, ist das Problem komplexer und lässt sich nicht allein durch einfache Helligkeitsanpassung lösen.

  • Mit lch kann man etwas Ähnliches machen

     --text: lch(from var(--bg) calc((49.44 - l) * infinity) 0 0);
    

    Quelle: https://til.jakelazaroff.com/css/…

    • LCH ist auch großartig, aber OKLCH ist noch besser. https://evilmartians.com/chronicles/oklch-in-css-why-quit-rgb-hsl/… Dieser Artikel hat meine Sicht komplett verändert. Es ist wirklich ein fantastisches Werkzeug. Überraschenderweise kannte keiner meiner Designer-Freunde OKLCH. Dieser Ansatz löst viele Probleme.

    • So eine CSS-Funktion, die Parameter auf diese Callback-Art empfangen kann, sehe ich zum ersten Mal. Ein wirklich interessantes Konzept. Ich frage mich, ob es außer lch noch andere Funktionen in diesem Stil gibt.

    • Lea Verou hat einen guten Artikel über einen ähnlichen Workaround geschrieben. https://lea.verou.me/blog/2024/contrast-color/

  • Dieser Artikel ist ein hervorragender Überblick über die Vor- und Nachteile der automatischen Kontrastauswahl. Wenn man eine einfache Website baut, ist das ein leichter und unkomplizierter Weg zu korrektem Kontrast.
    Wenn man aber WCAG-Compliance im großen Stil braucht, sollte man das vermeiden und stattdessen eine echte Ebene semantischer Format-/Design-Token verwenden. Semantische Token beschleunigen die Entwicklung und können visuell ansprechenderen Kontrast garantieren als ein simples Umschalten zwischen Schwarz und Weiß. Das Gute an einer semantischen Token-Ebene ist, dass sich Themes sehr leicht erstellen lassen, sodass Light-/Dark-Themes fast ohne Zusatzkosten möglich sind. Wenn eine Markenfarbe an WCAG2 scheitert, kann man sogar ein separates Theme für WCAG2/APCA erstellen, um Compliance zu erreichen und zugleich besseren Kontrast zu bieten.
    Ich arbeite in Figma am Variables-/Tokens-Stream und war auch an den Dark-Mode-Implementierungen von Figma und Atlassian beteiligt. Wenn jemand Fragen zu Tokens, Themes oder barrierefreien Farben hat, gerne her damit.

    • Mich würde interessieren, was mit semantischen Tokens konkret gemeint ist. Wegen genau solcher Anforderungen habe ich in einem großen Projekt CSS-in-JS für relative Farbberechnungen und Kontrastfarben verwendet. Ich hoffe, dass sich solche Techniken bald breit durchsetzen.

    • Der letzte Teil von 2/3 ist zu weitschweifig und wirkt unnötig verkopft. Auf Unternehmensseiten oder in Apps ist es riskant, sich auf so eine Funktion zu verlassen, weil die resultierende Farbe nicht vorhersagbar ist. Wenn WebKit einen Bug behebt, könnte sich das Farbergebnis ändern.

  • Ich tue mich noch schwer damit, zuzustimmen, dass eine Kontrastfarbe anhand der Entscheidung der Browserhersteller festgelegt wird, ohne dass das immer richtig oder vorhersagbar ist. Ich frage mich, ob es dafür einen deterministischen Standard geben wird, der in allen Browsern dasselbe Ergebnis liefert. Diese Funktion wirkt in der Praxis eher wie ein Hilfswerkzeug für UX-Teams in der Designphase.

    • Laut Artikel legt der Standard die Berechnungsmethode klar fest.

    • Das Wort „wählen“ wirkt missverständlich. Tatsächlich berechnet der Algorithmus eine Farbe.

    • Wenn man die Fehler bzw. Unklarheiten in der verlinkten APCA-Beispielformel ausklammert, funktioniert sie zu 100 % korrekt. Für perfekte Konsistenz könnte man, falls beide Kandidatenfarben (die hellere und die dunklere) gleichzeitig zulässig sind, anhand der Helligkeit (L*) der Hintergrundfarbe entscheiden, z. B. ab L* 60 die hellere wählen. Dann hätte man 100 % Konsistenz.

  • Ich fand es schwer nachvollziehbar, dass es in großen Projekten schwierig sein soll, gesondert darauf zu achten, dass Buttons nicht in unsichtbaren Farben enden, etwa dunkle Buttons mit schwarzem Text. Man könnte doch vor dem Release einfach alle Buttons einzeln prüfen. Oder man legt teamweit vorab fest, dass auf dunklen Buttons niemals schwarzer Text verwendet werden darf. Den Unterschied zwischen wahrgenommenem und mathematischem Kontrast fand ich interessant. Ich werde das in meinen Workflow übernehmen.

    • Eine vollständige Prüfung aller Buttons ist zwar möglich, aber auf diese Weise könnte allein die Phase für Regressionstests vorab Wochen, im schlimmsten Fall Monate dauern. In großen Projekten gibt es leicht mehrere tausend Buttons, und viele sind nur in bestimmten Optionskombinationen oder Workflows sichtbar.

    • Mit APCA lässt sich ein wahrnehmungsbasierter Kontrast berechnen.

  • Ich habe noch Buttons gestaltet, als Systemfarben populär waren. Es sah gut aus, aber man wusste nie, wie das Kontrastverhältnis ausfällt, deshalb hatte jemand per JavaScript mit getComputedStyle eine Berechnung eingebaut. Wenn der Kontrast unzureichend war, wurde eine zweite Farboption verwendet oder, wenn es unvermeidbar war, mit text-shadow der Kontrast um den Text herum verstärkt. Ich habe die genaue Berechnung vergessen, aber vielleicht reicht es schon, die drei RGB-Werte zu mitteln und zu vergleichen. Bei Blau wäre der Durchschnittswert niedriger, also könnte man weißem Text Vorrang geben.

  • Zumindest für Light-/Dark-Themes wäre es gut, Empfehlungen für sinnvolle Farben je Pseudoklasse wie active, focus, hover, link und visited zu bekommen. Material UI fügt hier noch Zustände wie disabled, before und after hinzu.

  • Ich habe früher einmal ein Video-Tutorial darüber gemacht, wie man je nach Hintergrundfarbe schwarzen oder weißen Text auswählt. Mein Ansatz war einfach: Ich habe die Farbe in Graustufen umgewandelt und danach entschieden, ob Schwarz oder Weiß verwendet wird. Es hat Spaß gemacht. Im Videoschnitt bin ich allerdings nicht besonders gut.
    https://youtu.be/tUJvE4xfTgo?si=vFlegFA_7lzijfSR (Achtung: Portugiesisch)

    • Interessanterweise hat ein anderer Kommentar genau die Farbformel vorgestellt, die das macht.
      https://news.ycombinator.com/item?id=44015990
      Das Video sieht auch ganz okay aus. Der Code wirkt gut, aber ich kann den Inhalt nicht beurteilen, weil ich kein Portugiesisch spreche.
  • Ich wähle das gesamte Farbschema ohnehin selbst aus, deshalb frage ich mich, warum es einfacher sein soll, die Kontrastfarbe für Button-Text automatisch zu wählen, statt sie von Anfang an einfach direkt selbst zu bestimmen. Diese Funktion scheint nur für einen sehr extremen Fall nützlich zu sein, in dem man Hintergrundfarben beliebig durcheinander auswählt, aber ausgerechnet die Vordergrundfarbe, also die Textfarbe des Buttons, nicht selbst bestimmen kann. Die eigentlichen Problemfälle sind doch Texte auf Bildern oder auf unterschiedlichsten Hintergründen, die immer gut lesbar sein müssen, und genau damit hilft diese Funktion überhaupt nicht. Daher wirkt es enttäuschend, dafür sogar ein neues Verb zu schaffen, obwohl die Funktion nur Schwarz oder Weiß auswählt und dafür auch noch den schlechtesten Kontrastalgorithmus (WCAG 2) verwendet. Wirklich beeindruckend.

    • Es ist schade, ein Werkzeug sofort abzutun, nur weil man selbst noch nie in eine Situation geraten ist, in der man es braucht. Es gibt viele Websites, auf denen Nutzer beliebige Farben auswählen können oder Farben aus hochgeladenem Material extrahiert werden. Websites, die auf Barrierefreiheit achten, müssen in solchen Fällen automatisch Kontrast berechnen. Wenn es dafür eine eingebaute CSS-Funktion gibt, wird grundlegende Barrierefreiheit deutlich einfacher. Natürlich schränkt das Entwickler in keiner Weise ein, wenn sie ein fortgeschritteneres Erlebnis schaffen wollen. Es wäre noch besser, wenn es ähnlich wie das npm-Paket contrast-color mehr Anpassungsmöglichkeiten gäbe, aber laut Blog wurde die Schwarz/Weiß-Auswahl erst einmal als erster Schritt umgesetzt, mit Plänen für spätere Verbesserungen.
      Beispiel: https://coolors.co/8fbfe0-7c77b9-1d8a99-0bc9cd-14fff7

    • Zur Kritik am schwachen Kontrastalgorithmus wurde klar gesagt, dass man dem WCAG-2-Algorithmus folgt und später leicht auf den entsprechenden Algorithmus von WCAG 3 umsteigen kann, sobald dieser standardisiert ist.

  • Ich frage mich, ob es Build-Time-Alternativen für so eine Funktion gibt, die sich in SASS, Tailwind usw. einsetzen lassen. Bis sich diese Funktion flächendeckend durchsetzt, dürfte es wohl dauern, und ich mache mir auch Sorgen, ob die Implementierung auf allen Plattformen wirklich gleich ausfallen wird.