Color contrast: the 4.5:1 rule and how to check it
Light gray text on white fails WCAG AA. squirrel measures the contrast of text whose color and background are both set inline, and reports pairs under 4.5:1.
What color contrast is
Contrast ratio compares the relative luminance of text and its background on a scale from 1:1 to 21:1. WCAG success criterion 1.4.3 Contrast (Minimum), Level AA, requires 4.5:1 for normal text and 3:1 for large text, where large means 18 point, or 14 point bold, and up.
The ratio is a property of the rendered pixels, so it depends on the stylesheet, the theme and any image behind the text. Static markup can only ever show part of the picture.
What squirrel checks
One check, color-contrast, at severity warning. It reports an element only when it has measured the element’s contrast ratio and the ratio is under 4.5:1. The 3:1 large-text allowance is not applied, so a large heading at 3.5:1 is still reported.
A pair is measured when the element’s own style attribute settles on both a color and an opaque background color, and the element has text. Within the attribute the last declaration of a property wins, and an !important one beats later ones without it. The background color comes from background-color, or from a background shorthand whose whole value is one color; any other shorthand, and a background-image other than none, leaves the background unresolved. A color counts when its whole value is a hex value (#rgb, #rrggbb, or a 4- or 8-digit hex whose alpha is fully opaque), an rgb()/rgba() value with three comma-separated channels of 0 to 255 and, if present, an alpha of 1 or 100%, or one of 31 named colors. squirrel computes the WCAG ratio and reports anything under 4.5:1 as span: #999 on #fff (2.85:1).
Everything else is left unresolved, and an unresolved pair is not a finding. axe-core treats it the same way, as “incomplete” rather than a violation. That covers:
- colors set in a stylesheet, whether external or in a
<style>block, or inherited from an ancestor; - class names, including Tailwind’s
text-gray-300and Bootstrap’stext-muted. A class says nothing about the surface the text lands on; transparent, any alpha below 1,inherit,currentcolor,var()and other syntax, because the color behind the text or of the text is not in the value. This holds when such a value is the winning declaration, even if an earlier one in the same attribute could be measured;- a background that may layer an image or a gradient, because there is no single color behind the text.
Findings are deduplicated, and the check reports N color contrast issue(s) below 4.5:1 with up to ten items and the count of measured pairs. With nothing under the threshold it passes as No obvious contrast issues detected whenever the page has any element with a style or class attribute, and on a page with neither it returns info with Limited contrast analysis available.
How to fix it
.muted {
color: #595959; /* 7:1 on white */
}Darken the foreground or lighten the background until the pair clears 4.5:1, and check the pair, not the color alone.
A pass covers only the pairs squirrel could measure. Most text takes its colors from stylesheets, so check the rendered page with browser DevTools or a contrast checker as well.
| Rule ID | a11y/color-contrast |
| Category | Accessibility |
| Scope | Per-page |
| Severity | warning |
| Weight | 5/10 |
Enable / disable
Disable this rule
[rules]
disable = ["a11y/color-contrast"]Disable all Accessibility rules
[rules]
disable = ["a11y/*"]Enable only this rule
[rules]
enable = ["a11y/color-contrast"]enable replaces the default ["*"], so this is the only rule selected. Leave disable out: a rule that matches any disable pattern is skipped even when enable names it. Only an enabled setting under a rule’s own [rule_options] table overrides both lists.
Related rules
- a11y/link-in-text-block: links told apart from body text by color alone.
- content/hidden-text: text hidden outright rather than made faint.
- a11y/focus-visible:
outline: nonein the page source with no:focus-visiblefallback. - mobile/font-size: small type, which makes a marginal ratio worse.
Accessibility findings ship in every audit next to the SEO, performance and agent experience rules. See Website security scan with AI for how an agent works through a report.
References
Check your site
Run squirrel audit https://example.com and open the Accessibility section of the report. The first ten deduplicated findings are listed, each with its computed ratio. Signed-out local audits need no account and cost nothing. Signed-in audits spend credits.