Hi, welcome to Word of Mike, my little corner of the internet. I am a Software/Web Developer working in North Yorkshire. I mainly write about programming but my other passion is politics so beware. (click to hide)

2012-08-18 16:08:39 UTC

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.