Maintaining Text Legibility Dynamically with JavaScript
Suppose you have a dynamically-defined arbitrary background colour for elements on your page, some of which may be dark, some may be light, but all have textual content. No single foreground colour can provide a satisfactory level of legibility for all possible background colours because of the contrast. You need a way to dynamically determine the lightness of the background, and apply a white or black foreground colour depending.
This was the problem I faced earlier in the week when a client noted that their choice of category colour was limited due to the hard-coded white text colour in our layout.
After not so long looking into the subject I read about a formula for calculating the "luminosity", or lightness or darkness of a colour, from a W3C guideline for legibility of textual content. I created a jQuery method to switch the foreground colour of my category badge elements between black and white, based on the lightness calculation of the background.
$(document).ready(doTextColour); function doTextColour () { var rgb, ca, r, g, b, bright, regex = /rgb\((\d+), (\d+), (\d+)\)/; // For each element with badge class $('.badge').each(function() { rgb = $(this).css("background-color"); // Get the RGB value of bg ca = regex.exec(rgb); // Split into red, green and blue r = parseInt(ca[1], 10); g = parseInt(ca[2], 10); b = parseInt(ca[3], 10); bright = (r*299 + g*587 + b*114) / 1000; // Calculate brightness /* If brightness value is greater than 125, make foreground colour black, otherwise make it white */ $(this).css("color", (bright > 125 ? 'black' : 'white')); }); }
The reason I put it in its own function is that I can now call the function again when I have loaded more badge elements AJAXically. Voila! That was simple.