WCAG 2.2 contrast on a photo

Text on an image Measured behind every letter

A photo behind text has thousands of colors, and the text has to read against the weakest of them. Put text on an example or on your own image: every pixel behind it is measured, the weakest spot is marked, and the lightest overlay that fixes it is worked out.

The workbench

Measure text on an image

Pick an example or use your own image, then move the text, change it and try an overlay. Every change is measured again at once.

The workbench needs JavaScript to read an image. The worked examples below read without it.

Example pictures

These four pictures are drawn by code rather than photographed, so every figure on this page can be checked.

Bright sky with clouds 1200 × 750 px

Drag the dashed frame to move the text, or its corner to resize it. With the frame focused, the arrow keys move it and Shift with an arrow key resizes it.
Overlay

Lowest contrast behind the text

Whole text frame

1.00:1

Fails Large text needs 3:1 AA

Median
1.95:1
Pixels that pass
11%
Pixels measured
—

How the measured pixels spread

  • Under 3:1 88.4%
  • 3 to 4.5:1 11.5%
  • 4.5 to 7:1 0%
  • 7:1 and up 0%

Weakest pixel #FFFFFF

Text and frame

Text
Text frame

Percentages of the image.

Measure

The fixes

Make it readable

Each fix is worked out for the text and frame above, from the picture without any overlay, one whole percent at a time. Use one to see it on the picture.

An even layer

—

The overlay color over the whole picture, at one strength.

Working it out…

Fading down from the top

—

Strongest at the edge nearer the text and clear at its reach, so more of the picture stays bright.

Working it out…

Plain text colors

White or black text on the same pixels, under the overlay as it is.

  • White text — Fails
  • Black text — Fails

CSS for this result

The overlay as a layer on the picture's box, and the text above it. It follows the controls above.

Worked examples

Four pictures, measured

Each example is measured over its whole text frame at 1200 pixels wide, at level AA, with no overlay; then the lightest black layer and fade that pass are worked out. Open one in the workbench to change anything.

Text on four pictures: the weakest pixel against the typical one, and the overlay each needs
PictureTextNeedsLowestMedianPixels that passEven black layerBlack fadeWorkbench
Bright sky with clouds Plan your summer#FFFFFF 56 px Bold 3:1 1.00:1 1.95:1 11% 42% From the top: none passes
Sunset over water Evening boat tours#FFFFFF 64 px Bold 3:1 1.47:1 5.60:1 97% 30% From the bottom: 60%
Leaves in dappled light Explore the trails#FFFFFF 48 px Bold 3:1 1.84:1 8.39:1 96% 23% From the bottom: 47%
City lights at night Open until midnight#FFF4D6 20 px Regular 4.5:1 2.55:1 16.25:1 74% 27% From the top: 37%
  • The median says almost nothing. Over the sunset, 97% of the pixels pass and the median is 5.60:1, yet the sun's path on the water brings the weakest pixel down to 1.47:1, and that is where the letters are hard to read.
  • A fade only helps where it is strong. The sky's text sits too far from the top edge: even a fade starting at full black is too faint by the time it reaches the letters, so only an even layer fixes it.
  • Smaller text needs more. The city's text is 20 pixels regular, so it needs 4.5:1 rather than 3:1, and a few bright lights behind it are enough to fail it.

The fades reach 60% of the picture's height, from the edge nearer the text.

Method

How it measures

  1. The picture is drawn at the width you choose, in sRGB with one byte per channel, the way a browser shows it on a page. A see-through image is drawn on white.
  2. The overlay is laid on each pixel the way a browser blends a color with an alpha: channel by channel, in sRGB, with the alpha in steps of 1/255. A fade is a linear gradient from the overlay at full opacity at the edge to transparent at its reach.
  3. Each pixel in the sampled area is compared with the text color by WCAG 2's contrast formula. The lowest of those ratios is the result: the text passes only if the weakest pixel reaches the target.
  4. "The whole text frame" takes every pixel inside the frame. "Around the letters only" takes the pixels the letters cover, as your browser draws them, and a margin of an eighth of the text size around them.
  5. The target is WCAG 2.2's: at level AA, 4.5:1 for normal text and 3:1 for large text, which is 24 pixels or more, or 18.66 pixels and bold; at level AAA, 7:1 and 4.5:1.
  6. The lightest overlay is found by trying every whole percentage from 0 to 100 with the overlay's kind and color, so the CSS printed is exactly what was measured.

The worked examples are recomputed by an automated test from the same code, so a figure on this page cannot drift from what the workbench measures.

Found a wrong number? Tell us.

Limits

What a measurement cannot tell you

  • WCAG does not say how to measure a photo. Its contrast ratio compares two flat colors. Holding text to the weakest pixel behind it is the strict reading, and W3C lists a background image without enough contrast as a failure of 1.4.3 and 1.4.6 (failure F83). A tool that samples one background color for a photo is giving you a guess.
  • Busy pictures are hard to read at any ratio. Fine detail behind thin letters breaks up their shapes even when every pixel passes. Contrast is measured here; clutter is not.
  • Letters are not solid blocks. The edges of letters are blended with the background, and thin or light weights read weaker than their ratio suggests.
  • Your layout moves the picture. With object-fit: cover, each screen width crops the image differently, so a different part of it sits behind the text. Measure at each width your design uses, with the image your site actually serves after compression.
  • Images change. A new photo next month needs measuring again. Only an overlay that passes over pure white holds for any picture. For white text, an even black layer does it at these opacities:
    • Normal text 54%
    • Large text 42%
  • Wide-gamut and HDR images are converted. The browser hands the page sRGB values, so a photo with colors outside sRGB is measured as sRGB shows it.
  • Shadows and outlines are not measured. A solid outline wide enough to surround every stroke can carry the contrast, but a soft shadow cannot be measured reliably, so treat it as a bonus on a background that already passes.
  • Words in the image file are a different problem. This measures real text laid over a picture. If the words are part of the image, they cannot be resized, translated or read by every screen reader, and WCAG 1.4.5 asks for real text instead.

In practice

Making text on an image readable

  1. Put the text where the picture is calm. Move the frame over an even, dark or light area and measure again; often that is all it takes.
  2. Lay an even layer over the picture. It is the one fix that holds for any future image, and the workbench gives the lightest that passes.
  3. Fade from the edge the text is near. A fade keeps more of the picture clear, but the text has to sit where the fade is still strong.
  4. Give the text its own background. A solid panel behind the words takes the picture out of the measurement: check the panel and the text with the contrast checker.
  5. Choose the text color the picture needs. Dark text often suits a light, airy image better than white text with a heavy layer: compare both under "Plain text colors".
  6. Make the text bigger or bolder. Large text needs 3:1 rather than 4.5:1 at level AA, which can be the difference between an overlay and none.

The rules: 1.4.3 Contrast (Minimum), 1.4.6 Contrast (Enhanced) and 1.4.5 Images of Text.

Where next

Check the rest of the page

From one picture to every pair on a page.