Elements must meet minimum color contrast ratio thresholds
Text that is too pale against its background is hard or impossible to read for customers with low vision, colour blindness or ageing eyes, and for anyone using a phone in sunlight. Prices, discount codes, form hints and button labels that cannot be read lead to mistakes and lost orders.
- Rule id
- color-contrast
- Source
- axe-core 4.13.0
- Impact
- Serious
- Fix tier
- ASSISTED
- on Shopify, Shopware, WooCommerce and Magento
- Status
- runs
What the check does
Ensure the contrast between foreground and background colors meets WCAG 2 AA minimum contrast ratio thresholds
Candidates are elements with a visible text node of their own, plus input, select and textarea fields, even empty ones, except a select without options and a field whose text-indent moves its text off the control. Skipped are textless inputs such as checkboxes, disabled or inert elements, labels of disabled controls, and text of only emoji or punctuation.
The check reads the computed text color and builds the background from the elements stacked behind the text, blending semi-transparent layers onto a white page. Text counts as large from a font-size of 18pt (24px), or 14pt (18.66px) when font-weight is 700 or more.
When the check cannot decide, the result is needs review, as with a background image or gradient, an image or video behind the text, another element on top, a large, absolutely positioned ::before or ::after with a background, or a single failing character. Validiscan’s scanner does not turn these into findings, so such text needs a person’s check.
Colors are read in the state the page loads in, with the light color scheme, at each scanned viewport. vs-hover-focus-contrast measures hover and focus states.
How to fix it
Raise the contrast of normal text to at least 4.5:1 and of large text (24px, or 18.66px bold) to at least 3:1. Adjust the colour in the theme settings or CSS variables rather than per element, keeping the brand hue and changing the lightness, and check text on images and sale badges too.
WCAG success criteria
- 1.4.3 Contrast (Minimum), level AA
EN 301 549 clauses
| WCAG criterion | Version 3.2.1 | Version 4.1.1 |
|---|---|---|
| 1.4.3 | 9.1.4.3 | 9.1.4.3 |
Recipes that list this rule
This rule has the tier ASSISTED. In a project, a finding of it takes the ASSISTED way, and these recipes are not applied to it.
Shopify: recipe contrast-tokens
Show the before and after (1)
assets/base.css.liquid Changes to assets/base.css.liquid: 3 added, 3 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 745 | 745 | font-size: 0.8125rem; | |
| 746 | 746 | letter-spacing: 0.04em; | |
| 747 | 747 | text-transform: uppercase; | |
| 748 | Removed | color: #929292; | |
| 748 | Added | color: #767676; | |
| 749 | 749 | } | |
| 750 | 750 | ||
| 751 | 751 | .rating { | |
| 1013 | 1013 | ||
| 1014 | 1014 | .copyright__content { | |
| 1015 | 1015 | margin: 0; | |
| 1016 | Removed | color: #929292; | |
| 1016 | Added | color: #6f6f6f; | |
| 1017 | 1017 | } | |
| 1018 | 1018 | ||
| 1019 | 1019 | .policies { | |
| 1077 | 1077 | ||
| 1078 | 1078 | .cookie-banner__text, | |
| 1079 | 1079 | .cookie-banner__link { | |
| 1080 | Removed | color: #9a9a9a; | |
| 1080 | Added | color: #767676; | |
| 1081 | 1081 | } | |
| 1082 | 1082 | ||
| 1083 | 1083 | .cookie-banner__icon-button { |
Shopware: recipe contrast-tokens
Show the before and after (1)
Resources/app/storefront/src/scss/_variant-broken.scss Changes to Resources/app/storefront/src/scss/_variant-broken.scss: 1 added, 1 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 45 | 45 | /* Light grey unit prices, 3.1:1 (color-contrast). */ | |
| 46 | 46 | .product-price-unit, | |
| 47 | 47 | .product-detail-price-unit { | |
| 48 | Removed | color: #929292; | |
| 48 | Added | color: #757575; | |
| 49 | 49 | } | |
| 50 | 50 | ||
| 51 | 51 | /* Fixed two-line product names (vs-text-spacing). */ |
WooCommerce: recipe contrast-tokens
Show the before and after (1)
assets/css/main.css Changes to assets/css/main.css: 1 added, 1 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 676 | 676 | .kb-footer-about, | |
| 677 | 677 | .kb-footer-newsletter-intro, | |
| 678 | 678 | .site-info { | |
| 679 | Removed | color: #888; | |
| 679 | Added | color: #6e6e6e; | |
| 680 | 680 | } | |
| 681 | 681 | ||
| 682 | 682 | .site-footer ul.menu { |
Magento: recipe contrast-tokens
Show the before and after (1)
app/design/frontend/Validiscan/fixture/web/css/source/_theme.less Changes to app/design/frontend/Validiscan/fixture/web/css/source/_theme.less: 1 added, 1 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 1099 | 1099 | // VALIDISCAN-SEEDED color-contrast: #929292 on white is 3.1:1. | |
| 1100 | 1100 | .block-promo .info, | |
| 1101 | 1101 | .toolbar-amount { | |
| 1102 | Removed | color: #929292; | |
| 1102 | Added | color: #767676; | |
| 1103 | 1103 | } | |
| 1104 | 1104 | ||
| 1105 | 1105 | // VALIDISCAN-SEEDED vs-reflow: the promo row keeps a 1100px minimum width at every breakpoint. |
app/design/frontend/Validiscan/fixture/web/css/styles-m.css Changes to app/design/frontend/Validiscan/fixture/web/css/styles-m.css: 1 added, 1 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 1075 | 1075 | ||
| 1076 | 1076 | .block-promo .info, | |
| 1077 | 1077 | .toolbar-amount { | |
| 1078 | Removed | color: #929292; | |
| 1078 | Added | color: #767676; | |
| 1079 | 1079 | } | |
| 1080 | 1080 | ||
| 1081 | 1081 | .block-promo-wrapper { |
Start with a free check of your shop.
Send your shop’s address. Validiscan scans it and replies with every failure the scan can prove, with the page and the code.
Request a free checkOr write to info@validiscan.com.
What the free check covers, and what it leaves out- You send
- your shop’s address
- Pages scanned
- up to 15
- You get
- every failure the scan can prove, with the page and the code
- On your shop
- public pages only; no login, nothing bought, no forms sent
- What it is not
- a full audit