Auto-Contrasting Text

Not everybody is awesome at reading. Some people have a hard time with the words, others have a hard time with the contrast of the letters and the background. We as designers/developers can’t help the first group of people, but we can certainly assist the second group, in the name of accessibility.

I recently came across a problem while creating a label-interface. The labels were Bootstraps, but you could create your own colors. The problem was that Bootstrap labels can only have one text-color: white. This is awesome if you’re using them as intended, but if I want a white or a light yellow label, reading the label was almost impossible, since there was not enough contrast.

The W3C was way ahead of me, and they actually have a formula for contrast calculations. Using this formula I created both a SASS Mixin and a JS function that reads the background color and decides whether the text should be light or dark. I implemented this in the project and it worked great, every label was perfectly legible.

I’ve embedded both the SASS Mixin and the plain JS function below, so you can use it in your own projects. Both should be optimized before use, I’ve tried to make them human-readable. They should be abstracted and minified for production use. I’ve also added Codepens for both so you can see how it works (don’t forget to scroll the Codepen for more colors) and play around with the code yourself.

Javascript

function getCorrectTextColor(hex){
	threshold = 130;
			
	hRed = hexToR(hex);
	hGreen = hexToG(hex);
	hBlue = hexToB(hex);
	
	function hexToR(h) {return parseInt((cutHex(h)).substring(0,2),16)}
	function hexToG(h) {return parseInt((cutHex(h)).substring(2,4),16)}
	function hexToB(h) {return parseInt((cutHex(h)).substring(4,6),16)}
	function cutHex(h) {return (h.charAt(0)=="#") ? h.substring(1,7):h}

	cBrightness = ((hRed * 299) + (hGreen * 587) + (hBlue * 114)) / 1000;
	if (cBrightness > threshold){return "#000000";} else { return "#ffffff";}	
}		

Javascript Demo

See the Pen JS function for accessible color contrast by David Halford (@davidhalford) on CodePen

SASS Mixin

@mixin text-contrast($n) {
  $color-brightness: round((red($n)*299)+(green($n)*587)+(blue($n)*114)/1000);
  $light-color: round((red(#ffffff)*299)+(green(#ffffff)*587)+(blue(#ffffff)*114)/1000);
  
  @if abs($color-brightness) < ($light-color/2){
    color: white;
  }

  @else {
    color: black;
  }
}

SASS Demo

See the Pen SASS mixin for accessible color contrast by David Halford (@davidhalford) on CodePen

Note that the SASS Mixin will only work once (obviously) with predefined colors. If you want real-time changes (like I did, depending on the color the user selected for the label) you'll need to modify the JS function and call it on any event that changes the background color of the element you're watching.

 

image credit

Header image: Pamela Link on Flickr