Archiv für den Monat: Oktober 2018

Barrierefreie Farbkontraste 2: der Sourcecode

OK jetzt gilts: man kann eine beliebige RGB-Farbe wählen und sich ausgeben lassen, welche der 140 benannten HTML-Farben einen guten (barrierefreien) Kontrast dazu liefert. Das kann man nicht nur für Schriften verwenden, sondern auch für Logos und Icons, die auf einen farbigen Hintergrund gesetzt werden sollen.

Voraussetzung ist eine Tabelle, in der die 140 Farben mit Color Group (Farbfamilie), Namen und Hex- und RGB-Notation gespeichert sind, ich zeig hier noch mal einen Ausschnitt:

mysql_farbtabelle

mysql_farbtabelle

Wie die Farben da reinkommen beschreibe ich jetzt hier nicht, das ging über ein Excel-Makro und ist letzendlich völlig wurst für die Funktionalität. Also, wir haben unsere Farbtabelle.

Jetzt brauchen wir eine Datenbankverbindung, die beschreibe ich hier auch nicht mehr extra. Dann muss wieder mal ein Formular her, für die Auswahl der Basisfarbe bietet sich der Input-Type Color an, bei dem man in den meisten modernen Browsern einen schicken Colorpicker angezeigt bekommt. Man könnte auch ein Eingabefeld für den Hex- oder RGB-Wert nehmen, das ist letztlich Geschmackssache. Also, los gehts, mit einer Datei namens farbnamen.php, die sieht zunächst so aus:

<!DOCTYPE html>
<html lang="de">
<style type="text/css">
h1,h2,h3{
    font-family:Arial;
}
</style>
<head>
<title>Colors Arbeitspapier</title>
</head>

<body>
<h1>Beispiel Contrast Colors mit HTML Named Colors</h1>

<form action="farbnamen.php" method="post">

      <h2>Bitte eine Farbe auswählen:</h2>
      <input type="color" name="farbe" value=""><br>
      <h2>Bitte eine Farbfamilie für die Kontrastfarbe wählen:</h2>
    <select name="farbfamilien">
        <option value="BLUE">Blau</option>
        <option value="GREEN">Grün</option>
        <option value="PURPLE">Violett</option>
        <option value="WHITE">Weiß</option>
        <option value="BROWN">Braun</option>
        <option value="YELLOW">Gelb</option>
        <option value="GRAY">Grau</option>
        <option value="RED">Rot</option>
        <option value="PINK">Pink</option>
        <option value="ORANGE">Orange</option>
      </select>
     <br><br>
    <input type="submit" name = "senden">
  
</form>

Das ist erstmal straightes HTML, zuerst kommt der Color Picker, dann das Dropdownfeld für unsere Farbfamilien, und das wars auch schon. Man könnte den Select auch mit einem Distinct aus der Datenbank füttern, das hab ich mir jetzt gespart und die 10 Einträge so reingeschrieben.

Los geht es wie immer wenn auf den Submit-Button geklickt wurde. Der Colorpicker liefert den Hex-Wert der gewählten Farbe, das Dropdownfeld den Namen der Farbfamilie. Den Hex-Wert zerlege ich in die einzelnen Komponenten, die brauche ich später um meine Funktion zur Berechnung der wahrgenommenen relativen Helligkeit damit zu füttern, dazu weiter unten mehr. Das Ganze sieht jetzt erstmal so aus:

startbildschirm

startbildschirm

Bei Klick auf das schwarze Farbkästchen poppt der Colorpicker auf, in Chrome beispielsweise sieht der so aus:

chrome_colorpicker

chrome_colorpicker

Das Dropdownfeld ist auch keine Überraschung:

dropdown

dropdown

Aber jetzt wirds gleich interessant, ich habe nämlich für die Zerlegung des Hex-Wertes in seine RGB-Komponenten eine schicke Funktion gefunden, das geht mit sscanf():

<?php
require_once('config.php');

if(isset($_POST['senden'])){
    
    
    echo "Sie haben diese Farbe gewählt:<span style='background-color:".$_POST['farbe']."'>Hexadezimalwert: ".$_POST['farbe']."</span><br>";
    
    $akt_farbe = $_POST['farbe'];
    
    //RGB-Werte aus hex holen
    $hex = $akt_farbe;
    list($r, $g, $b) = sscanf($hex, "#%02x%02x%02x");
        
    echo "<h3>Die relative Helligkeit beträgt: ".Brightness($r,$g,$b)."</h3>";
    echo "<h3>Kontrastfarbe aus der Farbfamilie ".$_POST['farbfamilien']."</h3>";
    echo "<hr>";
    $input_brightness = Brightness($r,$g,$b);

Mit der Funktion Brightness wird wie gesagt die wahrgenommene Helligkeit der gewählten Farbe bestimmt, Input-Parameter sind die drei RGB-Komponenten. Die Funktion selber sieht so aus:

//relative (wahrgenommene) Helligkeit aus RGB berechnen
function Brightness($r, $g, $b)
    {
       return sqrt(
          $r * $r * .241 + 
          $g * $g * .691 + 
          $b * $b * .068);
    }

Jetzt hole ich mir aus der Datenbank alle Farben, die zu der gewählten Farbfamilie gehören. Zuerst setze ich noch einen Flag $gefunden, der bleibt auf False wenn in der gewählten Farbfamilie keine Farbe mit einem ausreichenden Kontrastwert gefunden wurde und dient dann weiter unten zur Info-Ausgabe.

Dann gehe ich mit einem While über alle gefunden Farben und gebe nur diejenigen aus, bei denen eine Differenz > 130 zur relativen Helligkeit der vom Benutzer vorgegebenen Farbe gefunden wird.

//alle passenden Einträge der Farbtabelle ausgeben
        //Flag default  
        $gefunden = false;
        
        //Nur die Einträge der gewählten Farbfamilie auslesen
          $abfrage = mysqli_query($conn,"SELECT * FROM $table 
                    WHERE familie LIKE '".$_POST['farbfamilien']."' "); 
          while($row = mysqli_fetch_array($abfrage,MYSQLI_ASSOC)) 
          { 
            //RGB-Werte aus hex holen
            $hex = $row['hex'];
            list($r, $g, $b) = sscanf($hex, "#%02x%02x%02x");
            //Helligkeit bestimmen
            $row_brightness = Brightness($r,$g,$b);
            
            //Kontrastwert berechnen
            $differenz = abs($row_brightness - $input_brightness);
            
            //Nur Kontrast höher als 130 ausgeben (Wert ggf anpassen)
            if ($differenz > 130){
                //flag setzen wenn mindestens ein Kontrast > 130 gefunden wurde
                $gefunden = true;
            echo ' <span style="color:'.$row['farbname'].'">'.$row['farbname'].'</span>.'.$row['hex'].'rel. Helligkeit: '.$row_brightness.' Differenz: '.$differenz.'<br>'; 
            echo "<h1><span style='color:".$row['farbname']."; background-color:".$akt_farbe."'>".$row['farbname']." ist ein guter Kontrast</span></h1>";
            echo "<hr>";
            }
            
        } // ende von while $row...
if($gefunden==false){echo "Keine passende Kontrastfarbe in der Farbfamilie ".$_POST['farbfamilien']." gefunden";}

} //Ende von isset senden

Für die Ausgabe der passenden Kontrastfarben verwende ich Spans und formatiere sie mit den entsprechenden Farbwerten. Falls keine Farbe mit ausreichendem Kontrast gefunden wurde, gebe ich dies als Info aus. Das war’s!

Hier noch ein Screenshot der Ausgabe, als Besipiel habe ich als Grundfarbe Gelb und für die Kontrastfarbe die Farbfamilie Blau gewählt:

farben_ausgabe

farben_ausgabe

Fertig ist das Werkzeug zur Kontrastfarbenbestimmung. Zugegeben könnte man es noch wesentlich hübscher formatieren, aber die Funktionalität haut hin, das genügt mir jetzt erstmal. Schlanke noch nicht mal 100 Zeilen Code, das ist mal wieder was für mich und meine minimalistischen Freunde – viel Spaß beim Nachbauen!

Nachtrag

Jetzt konnte ich mir es doch nicht verkneifen, die ganze Sache noch ein bißchen ansehnlicher zu gestalten. Der Prototyp sieht jetzt so aus:

aufgehuebscht

aufgehuebscht

Die Farben hole ich mir natürlich aus der Datenbank, wenn ich dazukomme, schreib ich noch einen neuen Artikel darüber. Aber hier ist jetzt mal Schlussende, der Beitrag ist lang genug

 


 

 

Barrierefreie Farbkontraste – ich hab da so ne Idee

Also, wie man ausrechnet ob auf einem farbigen Hintergrund eine schwarze oder weiße Schriftfarbe besser lesbar ist, das hatten wir ja gerade eben schon mal. Jetzt ist der Kunde aber König, und man kommt auch mal in die Verlegenheit, eine farbige Schrift auf farbigem Grund darstellen zu sollen. Die Anforderung könnte also heissen: es soll eine grüne Schrift auf rotem Grund ausgegeben werden, und die soll möglichst gut lesbar sein. Da kann man einen Colorpicker nehmen und so ungefähr schauen was besser lesbar ist, aber das ist ja doch bloß Trial&Error. Es gibt auch Formeln, mit denen man so etwas berechnen kann, fündig wird man z.B. beim W3C, oder auf dieser Seite von nbtech. Nach deren Algorithmus kann man die „perceived brightness“, also die wahrgenommene Helligkeit einer Farbe als Wert zwischen 0=schwarz und 255=weiß berechnen. Das ist nicht trivial, weil z.B. grüne Töne vom menschlichen Auge als heller wahrgenommen werden als rote Schattierungen. Darum berechnet man die jeweilige wahrgenommene Helligkeit, und vergleicht die Farben dahingehend. Ein Unterschied von ca. 120 zwischen den zwei Farben wird nach W3C als ausreichender Kontrast angesehen. Die Formel lautet wie folgt:

brightness  =  sqrt( .241 R2 + .691 G2 + .068 B2 )

sqrt ist die Quadratwurzel, R, G, B sind unsere guten alten Bekannten Rot- Grün- und Blauanteil aus dem RGB-Farbraum, wie wir sie in HTML so gerne verwenden (ausführliche Infos hierzu z.B. hier bei W3Schools)

Gar nicht so einfach: was ist Rot, was ist Grün?

Auch das ist nicht trivial, weil von der Meinung des Betrachters abhängig. Ein dunkles Rotbraun mag für einen noch als Rot durchgehen, der nächste ordnet es schon den braunen Tönen zu. Ein sonniges Gelb kann auch als Orange gelten, und ein blaustichiges Grün als Blauton herhalten. Sowas kann man nicht berechnen, da kann man sich nur eine Krücke suchen und daran festhalten. Bei den 16,7 Mio vorhandenen RGB-Farben ist es auch ein Ding der Unmöglichkeit, überall die korrekte Farbfamilie zu bestimmen. Wir nehmen ein paar Farben weniger, das tuts als Arbeitshypothese auch.

Eine Untermenge: die benannten HTML-Farben

Ich habe da eine interessante Zusammenstellung der benannten HTML-Farben im Web gefunden. Bei https://htmlcolorcodes.com/color-names/ gibt es eine Tabelle der von allen modernen Browsern unterstützten benamsten Farben, die nach Farbfamilien (Color Groups) gruppiert ist. Auch bei w3schools gibt es eine gut gestaltete Seite über die Color Groups, nur sind sie da ein bißchen anders zusammengefaßt.

Die Seite von htmlcolorcodes.com habe ich mir mal als Arbeitsgrundlage geklemmt und in eine Datenbanktabelle gejagt. Es sollten eigentlich 140 Farben sein, auf der Seite sind aber 143 Farben aufgeführt. Die Tabelle enthält Duplikate, da werden Farben unter zwei verschiedenen Farbfamilien genannt. Ist jetzt aber nicht so schlimm, letztendlich ist die Information wertvoll, welche Farbtöne als Rot, Blau, Gelb usw. empfunden werden. Es gibt eine Liste von 10 Farbfamilien. Ich werde bei den englischen Bezeichnungen bleiben, schliesslich sind auch die HTML-Farbnamen in Englisch.

Hier mal die Liste der Farbfamilien, mit der jeweiligen Anzahl der zugeordneten Farben:

YELLOW    11
WHITE    17
RED    9
PURPLE    19
PINK    6
ORANGE    6
GREEN    23
GRAY    10
BROWN    17
BLUE    25

Wie gesagt, die Summe ist hier 143, nicht 140, aber das vernachlässigen wir jetzt mal. Dass Blue die meisten Farbtöne zugeordnet hat verwundert auch nicht weiter, da Blau nunmal eine sehr beliebte Farbe bei Webdesignern und Grafikern ist und im Web sehr häufig verwendet wird.

Wer sagt, dass das Rot ist?

Unter der Farbfamilie „Red“ sind 9 benannte Farben zu finden:

family_red

family_red

Da sieht man schon, daß die Zuordnung der einzelnen Farbtöne zu denen Farbfamilien ausgesprochen subjektiv und diskutabel ist, Lightcoral würde ich eher unter Pink einordnen. Wenn man sich die RGB-Werte dieser Farben anschaut, wird man auch nicht schlauer.

red_family_rgb

red_family_rgb

Es ist mitnichten so, dass diese Farben alle einen besonders hohen R-Anteil haben, Darkred ist zum Beispiel so ein Ausreisser mit 139 als R-Wert, dafür sind die G-und B-Werte Null. Ich hab lange rumgesucht, aber bisher keine praktikable Berechnungsmethode gefunden, mit der man x-beliebige Farbtöne einer der obengenannten Farbfamilien zuordnen kann. Deswegen verwende ich die Zuordnungen von htmlcolocodes.com, da hat man zumindest mal einen Anhaltspunkt.

Und wozu das Ganze?

Ganz einfach: mir schwebt sowas wie ein spezialisierter Colorpicker vor, in dem man eine frei wählbare Farbe vorgibt. Dann wählt man aus, aus welcher Farbfamilie die Kontrastfarbe kommen soll, und erhält einen oder mehrere Vorschläge, welche Farbtöne einen guten Kontrast bieten würden. Das als Arbeitshypothese. Mal sehen, wie weit ich damit komme.

Die Voraussetzung: eine MySQL-Tabelle mit allen 140 benannten Farben

Diese enthält die Farbfamilie, den Farbnamen, den Hex-Wert und den RGB-Wert. Die habe ich natürlich nicht per Hand eingehackt, da habe ich einen kleinen Umweg über ein Excel-Makro genommen, mehr wird nicht verraten. Die Tabelle sieht so aus, die Feldnamen sind selbsterklärend:

mysql_farbtabelle

mysql_farbtabelle

Das wird meine Ausgangsbasis. Und ich komme mit unter 100 Zeilen Code aus. Den Source gibt es dann im nächsten Beitrag.

Das kann ich einfacher: Kontrastfarbe berechnen

Heute war in The Whip (Ausgabe 759) ein Artikel darüber, dass Lyft ihren ColorBox-Algorithmus zur Berechnung der optimalen Kontrastfarbe Open Source zur Verfügung gestellt hat, hier mal der Link zum Artikel:

Lyft Open Sources ColorBox Algorithm for Building Accessible Color Systems

Ziel der Sache ist, schwarze oder weiße Schrift auf farbigem Grund mit einem Farbkontrast darzustellen, der möglichst gut lesbar und damit barrierefrei ist.

Ich hab mir den Source auf Github natürlich gleich mal angesehen, schließlich habe ich vor nicht allzulanger Zeit hier ein kleines Javascript vorgestellt (Kontrastfarbe automatisch berechnen) das genau diesen Zweck erfüllt. Was soll ich sagen, das Skript von Lyft ist recht eindrucksvoll und etliche Seiten lang. Ich mach das selbe, mit weniger als 80 Zeilen Sourcecode, und davon ist noch die Hälfte für die HTML-Ausgabe. Warum umständlich, wenns auch einfach geht 🙂