WCAG 2.2 contrast with transparency

See-through colors Measure what the screen shows

A color with transparency has no contrast of its own: part of what you see is whatever lies under it. Build the stack, choose the page under it, and see the two colors the screen shows, how they measure on any page, and fixes that keep the alpha.

What you get

  1. The colors the screen shows Every layer blended the way a browser paints it, so the ratio is the one people see.
  2. A page you choose White, black, your dark theme or any color under the see-through layers, and a chart of every grey.
  3. Fixes that keep the alpha A text or background color at the same opacity, or the nearest opacity that passes.
  4. Opacity on the element CSS opacity on a card fades its text and background together; that is measured too.

The workbench

Measure a see-through stack

Set each layer's color and opacity, and the page under them, or open an example. Every change is measured again at once.

The workbench needs JavaScript. The worked examples below read without it.

The stack, painted by your browser #121212
  1. Text #1D4ED8
  2. Background layer rgb(29 78 216 / 12%)
  3. Page under it #121212
The layers, from the top. Each one is blended onto the ones under it, and the screen shows the result.

Result

Text

What the screen shows

2.61:1 contrast as seen

Fails

Normal text needs 4.5:1 AA APCA Lc −18

Text as seen
#1D4ED8
Background as seen
#13192A
On a white page
5.53:1
On a black page
2.95:1
The same layers on every grey page from black to white. The strip shows the background as seen on each one; red is where the contrast falls short, and the dot is your page.

Passes on these grey pages

  • #E6E6E6–#FFFFFF

Text color at the same opacity

#4279FF 4.50:1

Text opacity, same color

No opacity of this color gets there.

Background color at the same opacity

No color at this opacity gets there.

Background opacity, same color

No opacity of this color gets there.

CSS for this result

/* Over a #121212 page: 2.61:1, needs 4.5:1 */
.element {
  background-color: rgb(29 78 216 / 12%);
  color: #1D4ED8;
}
/* What the screen shows on this page, as opaque colors: */
/* color: #1D4ED8; background-color: #13192A; */

Page under it

An opaque color: what shows wherever the layers above it are see-through.

Background layer

0% means no background layer: the text sits on the page.

Text or UI part

A color typed with an alpha, such as #0000008A or rgb(0 0 0 / 54%), sets the opacity too.

Opacity on the element

The opacity property on the element that holds the background and the text: both fade together. 100% means none.

Measure

Worked examples

Five see-through stacks, measured

Each example is measured at level AA on the page it names, and again on a white and a black page. Open one in the workbench to change anything.

Five stacks with transparency: the colors the screen shows, the contrast on their own page and on white and black, and a fix that keeps the alpha
StackLayersNeedsWhat the screen showsContrastOn white / on blackA fix that keeps the alphaWorkbench
Hint text at 38% Text rgb(0 0 0 / 38%)Background NonePage #FFFFFF16 px Regular 4.5:1 #9E9E9E / #FFFFFF 2.67:1 2.67:1 / 1.00:1 Opacity 54% 4.60:1
Brand blue at 80% Text rgb(37 99 235 / 80%)Background NonePage #FFFFFF16 px Regular 4.5:1 #5182EF / #FFFFFF 3.62:1 3.62:1 / 2.89:1 Text rgb(17 77 212 / 80%) 4.53:1
A tinted badge on a dark page Text #1D4ED8Background rgb(29 78 216 / 12%)Page #12121214 px Bold 4.5:1 #1D4ED8 / #13192A 2.61:1 5.53:1 / 2.95:1 Text #4279FF 4.50:1
A see-through border Border rgb(0 0 0 / 12%)Background NonePage #FFFFFF 3:1 #E0E0E0 / #FFFFFF 1.32:1 1.32:1 / 1.00:1 Opacity 42% 3.03:1
A toast at 70% opacity Text #D1D5DBBackground #1F2937Page #FFFFFFElement opacity 70%14 px Regular 4.5:1 #DFE2E6 / #626973 4.26:1 4.26:1 / 5.70:1 Element opacity 72% 4.50:1
  • Black text cannot get darker. Hint text at 38% measures 2.67:1, and no color at that opacity helps, because black is already the darkest; the opacity has to rise to 54%.
  • A colored text can keep its opacity. Brand blue at 80% falls short, but a darker blue at the same 80% passes, so the design keeps its see-through text.
  • The page under a tint decides. The same badge measures 5.53:1 on a white page and 2.61:1 on a dark one, because a 12% tint takes almost all of its look from the page.
  • A border needs 3:1 too. A black border at 12% is a common divider, but where it is the only edge of a field or a button it needs to reach 3:1, which takes 42%.
  • Opacity on a card fades both layers. At 70% the dark toast lets the white page through its background and its text alike, and contrast drops; at 72% it passes.

Method

How it measures

  1. The page under everything is opaque, so it is the starting point.
  2. Each layer is blended onto the colors under it, channel by channel: alpha × color + (1 − alpha) × what is under it. Like a browser, it stores alpha in steps of 1/255, mixes gamma-encoded sRGB values and rounds each channel to a whole number.
  3. With opacity on the element, the text and the background are first blended together inside the element, and the result is blended onto the page at the element's opacity, as CSS paints a group.
  4. The text as seen and the background as seen are compared with WCAG 2's contrast formula, and with APCA for reference.
  5. The chart repeats the measurement on each of the 256 grey pages from black to white.
  6. A color fix keeps its layer's opacity and its OKLCH hue and chroma, and moves only its lightness, by the smaller step that passes; an opacity fix keeps the color and finds the nearest whole percentage that passes.

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 measures what is shown. Its ratio compares two flat colors, so a see-through color is measured as it appears over its background, and it can pass in one place and fail in another. Check it on every page and theme it can appear on.
  • A rounded channel can differ by one. Browsers round blended channels their own way, so a hand calculation or another tool may land one step away; that moves a ratio in its second decimal place.
  • Only flat pages are measured. Under a photo or a gradient, the page changes from point to point; measure those with Text on an image or Text and gradients.
  • Blend modes and filters are not modeled. mix-blend-mode, backdrop-filter blur and color filters change the colors in ways a simple blend does not; check those with a screenshot.
  • Disabled controls are exempt. WCAG does not require contrast for text in an inactive control, which is where faded opacity is often used. Placeholder and hint text that people read is not exempt.
  • Wide-gamut and HDR colors are clipped. A display-p3 color is measured as sRGB shows it.

In practice

Making see-through colors readable

  1. Measure every page a layer can sit on. A tint or a faded text color that passes on your light theme can fail on your dark one; the chart shows every grey at once.
  2. Give each theme its own text color. Keep the see-through tint if you like it, and set the text color per theme with light-dark() or a theme token.
  3. Fade colored text by darkening it, not only by opacity. A darker shade at the same opacity keeps the look and the contrast.
  4. Use opaque colors for small text where you can. The flat colors under the CSS on this page give the same look on that page, and they do not change when the page does.
  5. Put opacity on the part that needs it. Opacity on a whole card fades its text too; an alpha on the background alone keeps the text at full strength.

The rules: 1.4.3 Contrast (Minimum), 1.4.6 Contrast (Enhanced) and 1.4.11 Non-text Contrast.

Where next

Check the rest of the page

From one see-through stack to every pair on a page.