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.
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:
- es2015 Bundle (Should work in recent chrome)
- es5 minified bundle (~73k)
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 }
Limitations
- 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.