contrast-computable

Color contrast is computable for rendered text

automaticWCAG 1.4.3, 1.4.6 (AAA)confidence: highseverity: seriousperceivable

Determines whether sufficient information is available to compute the color contrast for visible text (e.g., no gradients/images/blend modes that make background indeterminate).

Applies to. Applies to every visible text node in scope, plus the label of <input type="button">/[type="submit"]/[type="reset"], which is rendered from the value attribute and so is invisible to a text-node walk, and the text a form field shows: the current value of a <textarea> or of an <input> that shows text (text, search, email, url, tel, password, number, the date and time types), or, while the value is empty, its placeholder, in the ::placeholder color, font, opacity and background (only where the browser computes that style; jsdom does not). The text of a drop-down <select> (no multiple, a size of 1 or none, not appearance: base-select) counts as the select's, drawn by the closed control in its colors, font and background: its shown option, and any other option with the select's colors. In a browser, so is the text a ::before or ::after content generates (strings, attr() as the browser resolves it, counters), and a list item's ::marker text (a number or a letter, or a string; a bullet or an image isn't text), each judged in the pseudo-element's color and font, on its element; jsdom computes no pseudo-element styles, so there it is left out. Text counts only when its element is DOM-visible under the run's visibility mode, is not clipped out of sight by the sr-only technique (clip or clip-path), and belongs neither to a disabled control nor to the label of one, WCAG's inactive-user-interface-component exception. Subtrees excluded via engineOptions.excludeSelectors are skipped, and open shadow roots are walked as roots in their own right.

Expectation. Both sides of the contrast calculation can be established from CSS for every applicable text node: an effective background resolving to an opaque color, and a parsable foreground color. Where either cannot be, a background image or gradient (a gradient of one color is that color, and a layer that paints nothing under the text, such as a 1px underline, is left out), mix-blend-mode, a filter (other than drop-shadow() alone over an opaque background under all of the text, which hides the shadow) or backdrop-filter, a text-shadow (which may add contrast this engine has no glyph-rendering model to account for), a -webkit-text-stroke outline (drawn in its own color, often most of the glyph), a ::first-line or ::first-letter in a color of its own (which text it paints depends on line breaks), opacity on an ancestor, or on the text's own element over a background of its own, that can't be resolved against what lies behind it, a root background that never becomes opaque where the page's canvas can't be known (in a frame, under forced colors; elsewhere text is measured on the canvas, see contrast-minimum), a color that does not parse, or an option of a drop-down <select>, other than the shown one, with a color, background or opacity of its own (SELECT_OPTION_COLOR: it is shown only in the list the select opens, which the platform draws in those colors or in its own), or, in an emulator such as jsdom, a text color that can't be worked out in the color scheme the page is drawn in (COLOR_SCHEME_NOT_RENDERED), the result is cantTell naming the blocker. This rule is the one that reports that uncertainty, which is what lets contrast-minimum and contrast-enhanced stay silent on the same text instead of guessing at a ratio. One exception: text drawn by a stroke or a shadow, every color of which, its fill included when seen, is below the AA ratio against a flat background, fails contrast-minimum and contrast-enhanced, and is not asked about here.

What a finding reports.

  • blockerProperty, blockerValue (a CSS effect in the way): the CSS property that blocks the calculation and its value, for example mix-blend-mode, filter, text-shadow, -webkit-text-stroke or opacity.
  • blockerSelector (a CSS effect in the way): a selector for the element that has it, which may be an ancestor of the text.
  • backgroundFillType (a background image or gradient): image, gradient, imageAndGradient, or unknown.
  • background, backgroundAlpha (a background that never becomes opaque, or a color that does not parse): the background color as far as it could be worked out, as an rgba() string, and its opacity from 0 to 1.
  • eligibleTextCount (the pass): how many text nodes were checked.
  • assumptionsCount, assumptionsApplied (the pass): how many text nodes needed an assumption to get a background, and which ones were made. Each item is a code; ROOT_CANVAS_FALLBACK means a page background that never becomes opaque was taken to sit on the canvas color the scan names (contrast.rootCanvasFallback), or, with the auditorAssist mode where the page's own canvas can't be known (in a frame, under forced colors), on that color, white by default. Text measured on the canvas the page's color scheme gives it needs none.
  • generatedBy (generated text that can't be measured): ::before, ::after or ::marker, the pseudo-element whose text is asked about; the selector names its element. GENERATED_TEXT_UNREADABLE is content whose text can't be read (a counter in a style of the page's own), GENERATED_TEXT_POSITIONED a pseudo-element taken out of the flow with no opaque background of its own.
  • typography.fontSizePx, typography.fontSizePt (each text asked about): the font size as drawn, in CSS pixels and in points, as contrast-minimum reports it: the computed size times CSS zoom, an SVG scale or font-size-adjust. typography.declaredFontSizePx and typography.sizeScaledBy where it is drawn at another size than its font-size.
  • typography.fontWeight, typography.fontWeightLabel: the computed font weight as a number (400, 700) and as written.
  • typography.isBold, typography.isLargeText: whether the text counts as bold (700 or more), and as large text by core's definition (24px, or 14pt and bold), the size that only needs 3:1. Generated text has its pseudo-element's font, at its computed size.
  • The typography fields are a stable contract, as they are in contrast-minimum, unlike the rest of data.details.
  • forcedColors (every occurrence, when the colors measured were forced): true, and the hint says to check the page again with forced colors off. A scan under forced colors measures the page's own colors, so this is there only where it could not keep the page in them.

These data.details fields help to read and reproduce a finding. Apart from reasonCode and the few fields Output schema names as stable, they are not a stable contract: a field may be renamed or dropped in a minor release, so don’t build on them.

Examples

pass
<p style="background:#ffffff; color:#999999;">Body text</p>

Foreground and background are both flat, opaque colors, so a ratio can be computed (whether or not it later passes AA/AAA).

can't tell
<p style="background-image:url(texture.png); color:#000000;">Body text</p>

A background-image behind the text is not a flat color, so no contrast ratio can be computed at all.

How to check

When this rule can’t decide, it reports cantTell and leaves the question to a person. Each question it can ask is listed here under its reason code, with the steps to answer it. A finding carries the same steps as howToCheck, in the scan’s language. See Output schema.

ANCESTOR_OPACITY

  1. Find the text the report names and note the ancestor with opacity below 1.
  2. Use the color picker in the browser's developer tools, or a contrast calculator with colors picked by an eyedropper, to measure the text and background as they appear on screen (faded), with an eyedropper on the rendered page.
  3. Compare the ratio with 4.5:1 (3:1 for large text) for minimum contrast, and 7:1 (4.5:1 for large text) for enhanced contrast.

Pass. The faded colors on screen reach the threshold, or the faded text is an inactive (disabled) control, which is exempt.

Fail. The faded colors on screen give a ratio below the threshold, which fails WCAG 1.4.3 (or 1.4.6), unless the text is part of an inactive control.

BACKGROUND_FILTER_OR_BACKDROP_FILTER

  1. Find the text the report names and note the filter or backdrop-filter on it or an ancestor (in the developer tools Styles pane).
  2. Use the color picker in the browser's developer tools, or a contrast calculator with colors picked by an eyedropper, to measure the text and background colors as they appear on screen with the filter applied, using an eyedropper on the rendered page rather than the declared values.
  3. For a blur or backdrop-filter over changing content, scroll or wait so different content passes behind, and check the worst case.
  4. Compare the ratio with 4.5:1 (3:1 for large text) for minimum contrast, and 7:1 (4.5:1 for large text) for enhanced contrast.

Pass. With the filter applied, the ratio on screen reaches the threshold.

Fail. With the filter applied, the ratio on screen falls below the threshold, which fails WCAG 1.4.3 (or 1.4.6).

BACKGROUND_IMAGE_OR_GRADIENT

  1. Find the text the report names and look at the image or gradient behind it.
  2. Use the color picker in the browser's developer tools, or a contrast calculator with colors picked by an eyedropper, to measure the text color against the lightest and darkest parts of the background directly behind the letters.
  3. If the image changes (slides, video, responsive images), check each version and at a few window widths.
  4. Compare the ratio with 4.5:1 (3:1 for large text) for minimum contrast, and 7:1 (4.5:1 for large text) for enhanced contrast.

Pass. Every part of the background behind the letters gives at least the threshold ratio.

Fail. Some part of the background behind the text gives a ratio below the threshold, which fails WCAG 1.4.3 (or 1.4.6).

BACKGROUND_NOT_COMPUTABLE

  1. Find the text the report names on the page.
  2. Use the color picker in the browser's developer tools, or a contrast calculator with colors picked by an eyedropper, to measure the text color against the color seen directly behind the letters, taking the darkest and lightest points if it varies.
  3. Compare the ratio with 4.5:1 (3:1 for large text) for minimum contrast, and 7:1 (4.5:1 for large text) for enhanced contrast.

Pass. The ratio reaches the threshold everywhere behind the text.

Fail. The ratio is below the threshold anywhere behind the text, which fails WCAG 1.4.3 (or 1.4.6).

BACKGROUND_NOT_OPAQUE_AT_ROOT

  1. Find the text the report names; the page sets no opaque background behind it, so what shows there is the canvas the browser paints, or, in a frame, the page around it.
  2. View the page where it is shown: inside the page that embeds it, with forced colors off, and in each color scheme the page supports (light and dark).
  3. Use the color picker in the browser's developer tools, or a contrast calculator with colors picked by an eyedropper, to measure the text against the background actually seen in each setting.
  4. Compare the ratio with 4.5:1 (3:1 for large text) for minimum contrast, and 7:1 (4.5:1 for large text) for enhanced contrast.

Pass. The ratio reaches the threshold in every setting where the page is shown.

Fail. In some setting where the page is shown the ratio is below the threshold, which fails WCAG 1.4.3 (or 1.4.6).

BACKGROUND_OVERLAP

  1. Find the text the report names and check which element actually paints behind it (inspect it and toggle the overlapping element off and on).
  2. Use the color picker in the browser's developer tools, or a contrast calculator with colors picked by an eyedropper, to measure the text color against the color actually seen behind the letters.
  3. Compare the ratio with 4.5:1 (3:1 for large text) for minimum contrast, and 7:1 (4.5:1 for large text) for enhanced contrast.

Pass. The color actually behind the text gives at least the threshold ratio.

Fail. The color actually behind the text gives a ratio below the threshold, which fails WCAG 1.4.3 (or 1.4.6).

BACKGROUND_UNPARSABLE

  1. Find the text the report names and inspect the background color value in the developer tools (often a newer syntax such as oklch(), lab() or color()).
  2. Use the color picker in the browser's developer tools, or a contrast calculator with colors picked by an eyedropper, to measure the text color against the background as rendered on screen.
  3. Compare the ratio with 4.5:1 (3:1 for large text) for minimum contrast, and 7:1 (4.5:1 for large text) for enhanced contrast.

Pass. The ratio reaches the threshold.

Fail. The ratio is below the threshold, which fails WCAG 1.4.3 (or 1.4.6).

COLOR_SCHEME_NOT_RENDERED

  1. Open the page in a browser set to the color scheme the report names (blockerValue: light or dark), or emulate it in the developer tools (Rendering, prefers-color-scheme).
  2. Find the text the report names and use the color picker in the browser's developer tools, or a contrast calculator with colors picked by an eyedropper, to measure it against the background behind it.
  3. Compare the ratio with 4.5:1 (3:1 for large text) for minimum contrast, and 7:1 (4.5:1 for large text) for enhanced contrast.

Pass. In that color scheme the ratio reaches the threshold.

Fail. In that color scheme the ratio is below the threshold, which fails WCAG 1.4.3 (or 1.4.6).

ELEMENT_OPACITY

  1. Find the text the report names and note the opacity below 1 on its element.
  2. Use the color picker in the browser's developer tools, or a contrast calculator with colors picked by an eyedropper, to measure the text and background as they appear on screen (faded), with an eyedropper on the rendered page.
  3. Compare the ratio with 4.5:1 (3:1 for large text) for minimum contrast, and 7:1 (4.5:1 for large text) for enhanced contrast.

Pass. The faded colors on screen reach the threshold, or the faded text is an inactive (disabled) control, which is exempt.

Fail. The faded colors on screen give a ratio below the threshold, which fails WCAG 1.4.3 (or 1.4.6), unless the text is part of an inactive control.

ENGINE_EXCEPTION

  1. Find the text the report names (the check stopped early, so nothing was measured).
  2. Use the color picker in the browser's developer tools, or a contrast calculator with colors picked by an eyedropper, to measure the text color against the background directly behind the letters.
  3. Note the text size and weight to tell whether it counts as large (at least 24px, or 18.66px and bold).
  4. Compare the ratio with 4.5:1 (3:1 for large text) for minimum contrast, and 7:1 (4.5:1 for large text) for enhanced contrast.

Pass. The ratio reaches the threshold for its size.

Fail. The ratio is below the threshold for its size, which fails WCAG 1.4.3 (or 1.4.6).

FOREGROUND_UNPARSABLE

  1. Find the text the report names and inspect its color value in the developer tools (often a newer syntax such as oklch(), lab() or color()).
  2. Use the color picker in the browser's developer tools, or a contrast calculator with colors picked by an eyedropper, to measure the text color as rendered against its background.
  3. Compare the ratio with 4.5:1 (3:1 for large text) for minimum contrast, and 7:1 (4.5:1 for large text) for enhanced contrast.

Pass. The ratio reaches the threshold.

Fail. The ratio is below the threshold, which fails WCAG 1.4.3 (or 1.4.6).

GENERATED_TEXT_POSITIONED

  1. Find the element the report names and locate the text its ::before or ::after draws on screen (it is positioned away from its element).
  2. Use the color picker in the browser's developer tools, or a contrast calculator with colors picked by an eyedropper, to measure that text's color against whatever shows behind it at its actual position.
  3. Resize the window and scroll to check other positions where it may land on another background.
  4. Compare the ratio with 4.5:1 (3:1 for large text) for minimum contrast, and 7:1 (4.5:1 for large text) for enhanced contrast.

Pass. Wherever it lands, the generated text reaches the threshold.

Fail. Where the generated text lands, the ratio is below the threshold, which fails WCAG 1.4.3 (or 1.4.6).

GENERATED_TEXT_UNREADABLE

  1. Find the element the report names and look at the text its ::before, ::after or list marker draws (a number, bullet or label).
  2. Decide whether it is text people need to read (a number, word or label) or a purely decorative shape.
  3. If it is text, use the color picker in the browser's developer tools, or a contrast calculator with colors picked by an eyedropper, to measure its color against the background behind it.
  4. Compare the ratio with 4.5:1 (3:1 for large text) for minimum contrast, and 7:1 (4.5:1 for large text) for enhanced contrast.

Pass. The generated text reaches the threshold, or it is purely decorative.

Fail. The generated text is readable content and its ratio is below the threshold, which fails WCAG 1.4.3 (or 1.4.6).

MIX_BLEND_MODE

  1. Find the text the report names and note the mix-blend-mode on it or its container.
  2. Use the color picker in the browser's developer tools, or a contrast calculator with colors picked by an eyedropper, to measure the blended text and background colors as they appear on screen, with an eyedropper on the rendered page.
  3. If different content can sit behind it (scrolling, sliders), check the worst case.
  4. Compare the ratio with 4.5:1 (3:1 for large text) for minimum contrast, and 7:1 (4.5:1 for large text) for enhanced contrast.

Pass. The blended colors on screen reach the threshold.

Fail. The blended colors on screen give a ratio below the threshold, which fails WCAG 1.4.3 (or 1.4.6).

PSEUDO_ELEMENT_COLOR

  1. Find the text the report names and note the ::first-line or ::first-letter color in the Styles pane.
  2. Use the color picker in the browser's developer tools, or a contrast calculator with colors picked by an eyedropper, to measure both the element's text color and the first-line or first-letter color against the background.
  3. Resize the window to see that the first-line color applies to different words at different widths.
  4. Compare the ratio with 4.5:1 (3:1 for large text) for minimum contrast, and 7:1 (4.5:1 for large text) for enhanced contrast.

Pass. Both colors reach the threshold.

Fail. Either color gives a ratio below the threshold, which fails WCAG 1.4.3 (or 1.4.6).

SELECT_OPTION_COLOR

  1. Find the drop-down the report names and open it with the mouse and with Alt+Down Arrow.
  2. Use the color picker in the browser's developer tools, or a contrast calculator with colors picked by an eyedropper, to measure each option's text against its background in the open list, including the highlighted option, in each browser the page supports.
  3. Compare the ratio with 4.5:1 (3:1 for large text) for minimum contrast, and 7:1 (4.5:1 for large text) for enhanced contrast.

Pass. Every option in the open list reaches the threshold.

Fail. An option in the open list gives a ratio below the threshold, which fails WCAG 1.4.3 (or 1.4.6).

TEXT_SHADOW

  1. Find the text the report names and note its text-shadow.
  2. Use the color picker in the browser's developer tools, or a contrast calculator with colors picked by an eyedropper, to measure the text fill color against the background.
  3. If the fill fails, zoom in and check whether the shadow forms a solid outline or halo around every letter; if so, measure the shadow color against the background and the fill against the shadow.
  4. Compare the ratio with 4.5:1 (3:1 for large text) for minimum contrast, and 7:1 (4.5:1 for large text) for enhanced contrast.

Pass. The fill reaches the threshold against the background, or a solid halo surrounds every letter and gives the threshold ratio.

Fail. Neither the fill against the background nor a solid halo around the letters reaches the threshold, which fails WCAG 1.4.3 (or 1.4.6).

TEXT_STROKE

  1. Find the text the report names and note its -webkit-text-stroke width and color.
  2. Use the color picker in the browser's developer tools, or a contrast calculator with colors picked by an eyedropper, to measure the fill color against the background, and the stroke color against the background.
  3. Zoom in to see which color forms most of each letter (a thin stroke counts less than the fill).
  4. Compare the ratio with 4.5:1 (3:1 for large text) for minimum contrast, and 7:1 (4.5:1 for large text) for enhanced contrast.

Pass. The fill and stroke both reach the threshold, or the color that clearly forms the letters does.

Fail. The color that forms the letters gives a ratio below the threshold, which fails WCAG 1.4.3 (or 1.4.6).

View source