Color Contrast Implementation
This document describes the implementation of the first phase of Color Contrast, its scope, and its limitations.
Scope
Initially, we focus on elements with text. Color contrast issues must be reported for text elements in their different states:
- Normal
- Active
- On Hover
- On Focus
Only the normal, hover, and focus states are currently being considered. Analyzing contrast activations for more complex controls requires advancing in intelligent page navigation.
Already covered
Two cases that were out of scope in the first phase are now analyzed:
- Backgrounds that are not a solid color. When the background is an image or a gradient, there is no single value to compare against, so the element is resolved through visual analysis of the rendered element instead of a plain color comparison.
- Text inside shadow DOM, and content generated by
::before/::after. Both are detected and analyzed.
Out of Scope
- Elements that do not contain text. Non-text contrast is a separate criterion, covered under 1.4.11.
- Hover and focus when the element that reacts to these events is the parent of the element to be analyzed. https://github.com/a11ysolutions/a11y-issue-detector/issues/107#issuecomment-2850266687
Where a background is built from several stacked layers — image plus overlay plus blend mode or filter, or a background fixed to the viewport — the element is still analyzed, but the resulting color is an approximation rather than an exact value. See Gradient limits.
Implementation
Element Collection
The first step is to collect all elements with text on the page. These elements must meet the following criteria:
- They are visible
- They have visible text or a placeholder
- They are not images
- They are a control of type
input,textarea, orselect; or they have no children unless they are pure text nodes or of typeb,strong, etc.
Element Analysis
Each element selected in the previous step undergoes a color contrast analysis.
Foreground Color Calculation
The foreground color is obtained by computing the color style.
Background Color Calculation
The background color is obtained in two steps:
- The initial background is the background color of the first ancestor without a transparent background color
- While the background color opacity is less than 1, the current background color is blended with the background color of the nearest ancestor with a non-transparent background color.
The process ends when a background color with opacity equal to 1 is obtained, or when there are no more ancestors.
Once the two colors are obtained, the luminosity of both is calculated along with the color contrast. A color contrast violation is then determined according to established rules that consider the font size and weight of the text.
Special Case: Hover with inset box-shadow
In certain designs:
- The
inset box-shadowhas a high spread (e.g., 20px) and large blur (e.g., 10px). - The result is that it fully covers the background, acting as a solid background.
Implemented behavior
To address this:
- When an inset
box-shadowthat visually covers the area is detected, the detector: → prioritizes the color derived from the box-shadow → instead of the traditional background or image.
This allows reporting the contrast correctly even when the final visible color comes from the shadow.
Limitation
Due to variation in:
- intensity,
- blur,
- spread,
- multiple compositions,
there may be small discrepancies between the calculated color and the actual browser render. However, this provides a more faithful representation than the previous approach based solely on the background image.
