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
- The colors the screen shows Every layer blended the way a browser paints it, so the ratio is the one people see.
- A page you choose White, black, your dark theme or any color under the see-through layers, and a chart of every grey.
- Fixes that keep the alpha A text or background color at the same opacity, or the nearest opacity that passes.
- 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.
- Opacity on the element
- Text
#1D4ED8 - Background layer
rgb(29 78 216 / 12%) - Page under it
#121212
Result
TextWhat 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
Nothing here lets the page show through, so every page gives the same result.
Passes on these grey pages
- #E6E6E6–#FFFFFF
None: it fails on every grey page.
Already passes. Nothing to change.
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.
Opacity on the element
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; */
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.
| Stack | Layers | Needs | What the screen shows | Contrast | On white / on black | A fix that keeps the alpha | Workbench |
|---|---|---|---|---|---|---|---|
| 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
- The page under everything is opaque, so it is the starting point.
- 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.
- 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.
- The text as seen and the background as seen are compared with WCAG 2's contrast formula, and with APCA for reference.
- The chart repeats the measurement on each of the 256 grey pages from black to white.
- 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
- 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.
- 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.
- Fade colored text by darkening it, not only by opacity. A darker shade at the same opacity keeps the look and the contrast.
- 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.
- 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.
- Contrast hubWhat WCAG 2.2 asks for, the maths, and the nearest passing color for any pair.
- Contrast checkerOne pair in depth: APCA beside WCAG, a palette matrix and a link you can share.
- Text on an imageEvery pixel behind the letters measured, the weakest spot marked, and the lightest overlay that passes.
- Text and gradientsEvery point of a gradient behind the text, or inside gradient text, with the weak stretches and fixes.
- Bit depth, channels and alphaHow alpha is stored and how a browser blends it.