Contrast analysis widget.

By Ada Rose Edwards, 12 February 2016

It is important that sites maintain legibility of all their text content for all of their users. Low contrast text can make it very difficult for some readers to read some text. This was inspired by Lea Verou's Contrast Ratio tool which works out the contrast between foreground and background colours and gives a numerical answer to whether it has enough contrast.

In order to locate potential problem areas on a website I put together this tool which shows the distribution of contrast ratio and can highlight elements on the page with poor contrast.

It's running automatically on this page and it is a bookmarklet so you can run it on almost any site provided the Content Security Policy allows.

This tool was inspired by Lea Verou's work on site contrast and uses some code from her Contrast Ratio utility.

Drag the Bookmarklet to your bookmark bar:  Analyse Contrast

Firefox: Fallback bookmarklet, works in firefox, doesn't work offline:  Analyse Contrast

Examples of bad contrast

Push the "Highlight Low Contrast Elements" button to see these highlighted.

Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

Scripts for automated testing

As well as a bookmarklet to enable it's use with automated tests I also compiled it as a script you can inject into the page once it has loaded. They can be configured to just show the graph or highlight the problem areas. The results are attached to the window so you can easily retrieve the results.

Scripts you can inject with webdriver or put in your phantomjs script to perform analysis:

These scripts will perform the analysis automatically and attach the results to the window (window.contrastWidgetData.) The data format is as follows:
window.contrastWidgetData = {
	"badContrastNodes": [
			"node": DOM Node,			 // Node which is below threshold
			"contrastRatio": 2.6		  // contrast ratio of the node
	"proportionBadContrast": 7.0495,	  // Proportion of characters below threshold
	"chartData": [ Number × 16 ]		  // Data to produce the chart from 0 to >15,
	"highlightBadEls": Function		   // function to highlight bad elements

Optional: To configure the script inject into the page a settings object BEFORE you inject the script.

window.contrastWidgetOptions = {
	badNodeCutOff: 4.5,		 // The threshold for poor contrast.
	showModal: true,		  // whether to show the modal with the graph
	highlightBadEls: false	// whether to highlight the bad nodes


  • Background Images and Gradients will be ignored, but it is good practise for these to have a similar 'background-color' regardless to fall back to in case of a lack of gradient support or the image fails to load.
  • Text in 0px2 area DOM nodes which have background colour will still have that background colour used.
  • The node highlighter will mis-highlight transformed elements (scale, translate etc..)
  • The highlight of highlighted 'position: fixed' elements will differ in position after a scroll
  • The widget will be unable to check for updates if used on pages in which the csp disallows, this will not effect the function of the bookmarklet.

How it works

The bookmarklet iterates over all text nodes in the document and collects their parents in a Set.

We then iterate over the Set of parents and use getComputedStyle to measure the color of the type.

We have to be a bit smarter to measure the background color we traverse up the tree until we find a parent with a background color declared.

These values are then used with the color lib from Lea Verou's tool, to work out a value the contrast.

We then sum the number of characters contained in that DOM node and use that to produce the small chart.

Potential Additional Features

  • Identify type which is too small.
  • Make it much slower but increase accuracy for layered semi-transparent nodes by collecting the background color from the first opaque node above the leaf node down to the leaf node we are measuring. Layer these in a canvas, then measure the colour of the canvas to work out the aggregate color.


Github Page with build instructions.