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. 151 | 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.
152 | 153 |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.
154 | 155 |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.
156 | 157 |This tool was inspired by Lea Verou's work on site contrast and uses some code from her Contrast Ratio utility.
158 | 159 |Drag the Bookmarklet to your bookmark bar: Analyse Contrast
160 | 161 |Firefox: Fallback bookmarklet, works in firefox, doesn't work offline: Analyse Contrast
162 | 163 |Examples of bad contrast
164 |Push the "Highlight Low Contrast Elements" button to see these highlighted.
165 |Scripts for automated testing
175 |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.
176 |177 | Scripts you can inject with webdriver or put in your phantomjs script to perform analysis: 178 |
-
179 |
- es2015 Bundle (Should work in recent chrome) 180 |
- es5 minified bundle (~73k) 181 |
184 | window.contrastWidgetData = {
185 | "badContrastNodes": [
186 | {
187 | "node": DOM Node, // Node which is below threshold
188 | "contrastRatio": 2.6 // contrast ratio of the node
189 | }
190 | ],
191 | "proportionBadContrast": 7.0495, // Proportion of characters below threshold
192 | "chartData": [ Number × 16 ] // Data to produce the chart from 0 to >15,
193 | "highlightBadEls": Function // function to highlight bad elements
194 | }
195 |
196 |
197 |
198 | Optional: To configure the script inject into the page a settings object BEFORE you inject the script.
199 |
200 | window.contrastWidgetOptions = {
201 | badNodeCutOff: 4.5, // The threshold for poor contrast.
202 | showModal: true, // whether to show the modal with the graph
203 | highlightBadEls: false // whether to highlight the bad nodes
204 | }
205 |
206 | Limitations
207 |-
208 |
- 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. 209 |
- Text in 0px2 area DOM nodes which have background colour will still have that background colour used. 210 |
- The node highlighter will mis-highlight transformed elements (scale, translate etc..) 211 |
- The highlight of highlighted 'position: fixed' elements will differ in position after a scroll 212 |
- 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. 213 |
How it works
216 |The bookmarklet iterates over all text nodes in the document and collects their parents in a Set.
217 |We then iterate over the Set of parents and use getComputedStyle to measure the color of the type.
218 |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.
219 |These values are then used with the color lib from Lea Verou's tool, to work out a value the contrast.
220 |We then sum the number of characters contained in that DOM node and use that to produce the small chart.
221 | 222 |Potential Additional Features
223 |-
224 |
- Identify type which is too small. 225 |
- 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. 226 |