Text over image contrast accessibility: how to check photos

Text over an image must meet the same WCAG contrast minimums as other text: 4.5:1 for normal text and 3:1 for large text at Level AA. A photo has no single background color, so measure its weakest spot behind the text, not one pixel, and fix a failing spot with an overlay, panel or new position.

Published . Last reviewed .

A headline set over a hero photo is easy to approve and hard to measure. The text can be readable at the spot where someone looked and unreadable a few hundred pixels along the same line. This guide covers how WCAG treats text over images, why a single sample point gives the wrong answer, how to measure the worst case, and what overlays, panels, text shadows, responsive crops and video backgrounds do to the result.

Low contrast is the most frequent error type in the WebAIM Million report of February 2026, which found low contrast text on 83.9% of home pages. This guide is the photo-specific companion to our color contrast guide, which covers the ratios and flat color pairs.

What WCAG says about text over images

Success criterion 1.4.3 Contrast (Minimum) (Level AA) requires a ratio of at least 4.5:1 between text and its background, or 3:1 for large-scale text. Level AAA 1.4.6 raises those to 7:1 and 4.5:1. Large text means at least 18 point, or 14 point and bold, per WCAG 1.4.3; our color contrast guide lists the pixel equivalents. Our 1.4.3 page and the criteria reference give the full context, and which WCAG version to use depends on where you operate.

Three points from W3C matter for photos:

  • The background is whatever the text is painted on. W3C's note on the contrast ratio says contrast is measured against the specified background over which the text is "rendered in normal usage".
  • W3C's own test starts from the worst case. Failure technique F83 lists background images that do not give text enough contrast as a failure of 1.4.3 and 1.4.6. Its quick check compares the text with the darkest area of the image for dark text, or the lightest area for light text. If that passes, there is no failure. If it fails, the test moves on to the background behind each letter, and only a failure there counts as a failure of the technique. A box drawn around a whole headline is therefore a stricter, safer measurement than F83 requires. How WCAG applies to a varying background is a judgment call, and the numbers in this guide are evidence for that call.
  • One exception is easy to over-read. The criterion exempts text that is "part of a picture that contains significant other visual content", such as a street sign in a photograph. In our reading, a headline a designer places on top of a photo is not part of the picture, so we treat it as covered.
What W3C's pages on 1.4.3, F83 and G18 say about text over images, and what they leave open
TopicWhat the pages saySource
A photo behind textA failure of 1.4.3 and 1.4.6 when it does not give enough contrast. Test the darkest or lightest area first, then the area behind each letter.F83
Where contrast is measuredAgainst the specified background over which the text is rendered in normal usage.Understanding 1.4.3
A border around lettersA narrow border is used as the letter. A wide border that fills in the inner details of the letters acts as a halo and counts as background.Understanding 1.4.3, note 5
A halo or outline as a fixSuggested alongside darkening the background behind a letter: a thin black outline at least one pixel wide, or a halo.G18
CSS text shadowsNot mentioned by name in these pages.None
Video behind textNot mentioned in these pages.None
Responsive layouts and cropsNot mentioned in these pages.None

Where the pages are silent, the sections below say so and label what is our own reasoning.

Why one sample point gives the wrong answer

The example below is original and illustrative. Picture a coastal hero photo with a white headline running left to right. The water behind the left of the line is deep navy and the sky behind the right is pale, ending in a bright cloud. Take five flat patches along the line (the colors are invented for illustration, not sampled from a real photo) and compute each ratio with the WCAG 2.2 formulas, using the same contrast code as our contrast checker and image contrast checker.

White (#FFFFFF) text against five invented patches along one line of an imagined hero photo (illustrative, not measured)
PatchWhere it sitsColorRatio with white textAA normal text (4.5:1)AA large text (3:1)
AFar left, deep water#1B3A5C11.62:1PassPass
BLeft of center, mid water#3F6E9E5.33:1PassPass
CCenter, low sky#7FA6CB2.55:1FailFail
DRight of center, pale sky#BFD7EA1.48:1FailFail
EFar right, cloud#F2F7FB1.07:1FailFail

Ratios here are truncated to two decimals, never rounded up, as in our tools. W3C says contrast ratios should not be rounded, and gives 4.499:1 as an example that does not meet 4.5:1 (Understanding 1.4.3).

Which number you report decides the verdict:

  • One clicked pixel. Sample patch A and you read 11.62:1, a comfortable pass.
  • The average. The five patches average to #829FBC, which gives 2.75:1, a fail.
  • The worst spot. Patch E gives 1.07:1, close to white on white. Three of the five patches fail at both thresholds.

For light text, F83's quick check uses the lightest area of the image, which here is patch E. That is why a single sample is not a test: a reader cannot choose which part of the background a word lands on.

Changing the text color does not rescue a background that runs from dark to light. Dark text (#14120D) on the same patches gives 1.60:1, 3.50:1, 7.32:1, 12.58:1 and 17.35:1, so the failure moves to the left end, where it is worst at 1.60:1.

Five patches are a simplification. A real photo has thousands of colors along the line, and our image contrast checker measures the background pixels in the box you draw: every pixel up to 1,000,000 in the box, a regular grid beyond that, with the soft edges of the letters set aside.

How to measure the worst case

The image contrast checker runs in your browser, and the image is not uploaded. It reads a picture, so give it a screenshot of the real page rather than the design file.

  1. Capture the page as it ships. Take a screenshot in the browser at the width you want to check. Scaling, color profiles and image compression all shift colors a little, so re-check anything borderline in the live page.
  2. Draw a box around all the text. Include some background around the letters, because the background is what is measured.
  3. Set the text color. Type the color from your CSS, or pick it from the image. The checker can suggest a color itself, but that is a guess about which color is the lettering, so the result is not a verdict until you confirm it.
  4. Choose the size and level. Normal or large text, AA or AAA.
  5. Read the worst case, not the median. The tool reports the worst ratio, the 5th percentile, the median and the share of the background that fails, and it only says a box passes if every measured pixel does.
  6. See where it fails. A heat map on the image and a plain-text table by part of the box show what to move or darken.

A box over 1,000,000 pixels is measured on a regular grid instead of pixel by pixel, and the result says which spacing it used.

What the image contrast checker cannot do

  • It measures the pixels of the image you give it, not the live page.
  • It assumes one text color. Gradient text, outlined text and text with a shadow are not modeled.
  • It cannot read: it does not know whether your box contains text, only which colors are in it.
  • It sets aside the soft edges of letters with a heuristic, so thin lines and fine texture in a photo can be set aside with them. When that could change the answer, the result gives both figures.
  • It checks text contrast only (1.4.3 and 1.4.6), not buttons, icons or focus rings.
  • A pass is a measurement of one image. It is not a statement that a page meets any standard or law.

Fixing a failing photo: overlays, panels and positioning

An overlay in this guide means a semi-transparent layer in your design, sometimes called a scrim, between the photo and the text. It is not an accessibility overlay widget, which is a different product class; see our overlay comparison.

Here is a black layer laid over the example photo, with the white text on top. Patch E, the cloud, is the worst case in every row.

Worst-case ratio for white text over the example photo, by opacity of a black overlay (illustrative)
Overlay opacityWorst patch (E) becomesRatioNormal text (4.5:1)Large text (3:1)
0%#F2F7FB1.07:1FailFail
30%#A9ADB02.26:1FailFail
40%#9194973.04:1FailPass
50%#797C7E4.20:1FailPass
52%#7477784.51:1PassPass
55%#6D6F715.04:1PassPass
60%#6163646.03:1PassPass

For this photo, a large headline clears 3:1 at 40% but only just, and body text needs 52%, which clears 4.5:1 by only about 0.01. Those margins are too thin to trust, because browsers round channel values and a screenshot is not the live page, so 55% is a safer choice. The numbers belong to this photo. Another photo needs its own measurement, and the overlay strength must be set from the brightest (or darkest) spot behind the text, not from the average.

Our 1.4.3 page uses a pure white pixel as the worst case, where 55% black gives 4.74:1. This photo's lightest patch is slightly darker than pure white, so the same overlay gives 5.04:1. Because even a pure white pixel under a 55% black layer leaves white text at 4.74:1, 55% is a reasonable starting value for white text. Measure your own photo anyway.

The layering in CSS looks like this:

.hero {
  position: relative;
  color: #fff;
  background: url("coast.jpg") center / cover;
}
.hero::before {
  content: "";
  position: absolute;
  inset: 0;
  background: rgb(0 0 0 / 0.55);
}
.hero > * { position: relative; }
Ways to fix text over an image, and what to watch for
FixWorks whenWatch for
Uniform overlayYou can accept a dimmer photo.Set the strength from the brightest spot behind the text, then measure again.
Gradient scrimThe text sits at one edge, such as the bottom third.The scrim must be strong enough at every point under the text, including where it fades out. Measure the whole box, not the middle.
Solid or semi-opaque panelThe photo is busy or varies widely.Measure the panel too. In the example, a navy panel (rgb(11 30 51)) at 85% opacity gives a worst case of 10.79:1.
Move the text or change the cropThe photo has a quiet area.Check every breakpoint, because the crop changes.
Change the text colorThe area behind the text is all dark or all light.It does not help when the photo spans both, as the dark-text figures above show.
Take the text off the photoThe words matter more than the picture.Put the text beside or below the image.
Set a fallback background colorAlways, whichever fix you choose.W3C treats a text color with no background color specified as a failure (WCAG 2.2 contrast ratio definition, note 4), so the text needs a color to sit on if the image does not load. Pick one close to the image's darkest or lightest tone, and measure it too.

Text that is part of the image file

Banners, social cards and promotional graphics often have words baked into the picture file. WCAG 1.4.3 still applies to that text unless the exception for pictures with significant other visual content holds, and an image that carries words needs a text alternative that conveys them (Understanding 1.1.1; see our alt text guide). To measure it, screenshot the graphic as it appears on the page and use the same box method.

Text shadows and outlines

Designers often add a soft shadow to make light text hold up on a busy photo. W3C's pages on 1.4.3, F83 and G18 do not mention CSS text-shadow by name. They do discuss borders and halos: note 5 of the Understanding page says a narrow border around a letter is used as the letter, while a wide border that fills in the inner details acts as a halo and counts as background. G18 suggests darkening the background behind a letter or adding a thin black outline at least one pixel wide.

WCAG gives no formula for a blurred shadow, whose strength depends on its blur, offset and opacity. Our advice, not W3C's, is to make the text pass against the image without counting the shadow, and to treat the shadow as extra margin. Our tools behave accordingly: the image contrast checker does not model text with a shadow, and its own page says to judge shadowed text by eye as well, and the accessibility bookmarklet does not measure text shadows.

Responsive crops

When a photo fills its box with background-size: cover or object-fit: cover, the crop changes with the viewport, and a different part of the photo ends up behind the text. The text itself also wraps differently as the width shrinks. W3C's pages above do not discuss responsive layouts. WCAG measures the page as it is rendered, so in our reading each layout you ship needs its own measurement.

  • Check at least three widths: a phone, a tablet and a wide desktop window.
  • Remember zoom. W3C notes that 320 CSS pixels is equivalent to a 1280 pixel window at 400% zoom, so the narrow crop is also the layout a desktop user sees at 400% zoom.
  • Check each swapped image if you use different pictures for different breakpoints.
  • Check the next upload. An editor who swaps the hero image changes the background. Put the overlay or panel in the template, with a margin, so it does not depend on one photo.

Video backgrounds

None of the W3C pages above mention video behind text. A video is a background that changes every frame, so the worst case is the lightest frame for light text, or the darkest for dark text, that ever plays behind the words. Our approach:

  1. Scrub through the whole loop and note the brightest and darkest scenes behind the text.
  2. Take screenshots of those frames in the browser at the layout width, and load each one into the image contrast checker.
  3. Fix the worst frame, not the first one. A constant overlay is usually the most dependable fix, because it does not change from frame to frame.

The bookmarklet does not guess here either: it lists text over a video, a picture, a gradient or an overlay as "check manually". Autoplaying motion has its own rule. Success criterion 2.2.2 (Level A, see the criteria reference) requires a way to pause, stop or hide moving content that starts automatically, lasts more than five seconds and is shown alongside other content, unless the movement is essential.

A routine for every banner and card

  1. Make the inventory. Run the accessibility bookmarklet on the page. Text over an image, gradient, video or overlay is listed for a manual check instead of being guessed at, and that list is your to-do list.
  2. Measure each one in the image contrast checker, at a narrow and a wide width.
  3. Fix the worst spot with an overlay, a panel or a new position, and measure again.
  4. Move the fix into the template so new images inherit it.
  5. Check what sits on top of the photo: buttons, icons and focus rings have a separate 3:1 test under 1.4.11 Non-text Contrast, covered on our 1.4.11 page.

For flat color pairs, use the color contrast checker. For the wider routine, see how to test website accessibility, the WCAG 2.2 checklist and the most common accessibility errors. Our site scanner reads HTML and cannot compute rendered contrast; what we check explains why, and why rule-based scanners miss issues covers the wider limit.

Text over image contrast questions

Does text over an image need to meet the contrast ratio?

Yes. WCAG 1.4.3 applies to text laid over a photo, and W3C lists background images that do not give text enough contrast as failure F83. At Level AA the minimum is 4.5:1 for normal text and 3:1 for large text, measured against the worst part of the image behind the words.

How do I measure contrast on a gradient or photo?

Measure the weakest spot behind the text, not one pixel. Screenshot the page, draw a box around the text in the image contrast checker, set the text color, and read the worst ratio and the share of the background that fails.

How dark should my overlay be?

There is no standard opacity. It depends on the brightest or darkest spot behind the text. In our worked example a black overlay needed 52% for normal text and 40% for large text, and we suggest leaving a margin on top of that. Measure your own photo.

Do text shadows count toward contrast?

W3C's pages on 1.4.3, F83 and G18 do not mention CSS text shadows by name. They do treat a narrow border around a letter as part of the letter. We advise making the text pass without counting the shadow and treating the shadow as extra margin.

Does text that is part of a photo need contrast?

Text that is part of a picture containing significant other visual content, such as a sign in a street photograph, has no contrast requirement under 1.4.3. In our reading, a headline placed over a photo is not part of the picture, so it is covered.

Can a scanner find low contrast over images?

Not reliably. A scanner that reads HTML cannot see the painted pixels, and our bookmarklet lists text over an image, gradient or video for a manual check instead of guessing. A person has to choose the text and judge the result.

Contrast over photos is one check among many

The free scan runs 16 rule-based WCAG checks on up to 3 pages of your site, including missing alt text, form labels, headings and link text. It reads HTML, so it does not compute rendered contrast; the tools above cover that. No signup.

Scan my site for free