How to Check and Fix Color Contrast Across Your Whole Site
Short answer: WCAG 2.1 AA requires a contrast ratio of at least 4.5:1 for normal text and 3:1 for large text and key interface components. Test with a browser tool or checker, then fix failures at the theme variable level so one change updates every page.
Low color contrast is one of the most common accessibility problems on the web, and one of the easiest to fix once you know where to look. This guide covers the ratios you need to meet, how to test your whole site rather than one page, how to fix failures at the source, and how to keep your brand colors while doing it.
This is general information, not legal advice. If you have questions about legal exposure, talk to an attorney.
What WCAG requires
Contrast is measured as a ratio between the lightest and darkest of two colors, from 1:1 (identical) to 21:1 (black on white). The relevant requirements in WCAG 2.1 Level AA are:
| What | Minimum ratio | Success criterion |
|---|---|---|
| Normal text | 4.5:1 | 1.4.3 Contrast (Minimum) |
| Large text | 3:1 | 1.4.3 |
| User interface components and graphics needed to understand content | 3:1 | 1.4.11 Non-text Contrast |
"Large text" means at least 18 point (about 24 CSS pixels) or at least 14 point (about 18.66 CSS pixels) if bold.
A few details trip people up:
- Ratios are not rounded. 4.49:1 fails 4.5:1.
- Placeholder text counts. Text in form fields has to meet the ratio like any other text.
- Links within body text need to be distinguishable from surrounding text by more than color alone, or meet a 3:1 contrast against the surrounding text, with an additional cue on hover and focus. A simple underline avoids the issue.
- Exceptions exist. Disabled controls, pure decoration, and logos or brand names are exempt from the text contrast requirement. Do not stretch these exceptions to cover real content.
The W3C explains the criterion in detail in its Understanding Contrast (Minimum) document.
How to check contrast
Check single colors
For a quick check of one pair, use a contrast checker. Enter the foreground and background hex values and read the ratio. Many are free, and browser developer tools include one.
In Chrome, Edge, and Firefox, inspect a text element and look at the color picker in the Styles panel. It shows the ratio and tells you whether it passes AA.
Check whole pages and templates
Checking colors one pair at a time does not scale. To find problems across a page:
- Run an automated scanner such as axe DevTools, Lighthouse, or WAVE. They flag most text contrast failures where the background is a plain color.
- Test each template type at least once: home page, article, product page, form, checkout, footer, and any pages with banners or modals.
- Test interactive states: hover, focus, active, error, and disabled-looking states. Scanners often miss states that only appear on interaction.
Know what automated tools miss
Automated tools struggle with:
- Text over photos, gradients, or video
- Text inside images (they can't read it at all)
- Colors set by scripts after the page loads
- Overlapping elements and semi-transparent layers
Plan on a manual pass for these. Zoom in and look at the page honestly: if you have to squint, a user with low vision will struggle more.
Fix contrast at the theme variable level
The fastest way to fix contrast across a site is to avoid fixing it page by page. Most modern themes, design systems, and page builders define colors once as variables or settings, then reuse them everywhere. Change the variable and every page updates.
Use CSS custom properties
If your stylesheet looks like this:
:root {
--color-text: #333333;
--color-text-muted: #9a9a9a;
--color-bg: #ffffff;
--color-link: #5fa8d3;
}
.muted { color: var(--color-text-muted); }
a { color: var(--color-link); }
then #9a9a9a on white is roughly 2.8:1 and #5fa8d3 on white is roughly 2.5:1. Both fail. Fix them in one place:
:root {
--color-text-muted: #595959; /* about 7:1 on white */
--color-link: #1a5f8a; /* about 6.9:1 on white */
}
Every element using those variables is corrected at once. Verify the exact ratios with a checker before you ship, since approximate numbers are only a guide.
In WordPress and page builders
Many themes keep colors in the Customizer, Site Editor (global styles), or a theme options panel. Start there before editing individual blocks. Look for:
- Body text and heading colors
- Link and button colors
- Muted, secondary, or "meta" text colors
- Footer and sidebar colors
- Form field borders and placeholder colors
Hard-coded colors set on individual blocks or widgets override global settings, so search for those afterward. For more on this platform, see the WordPress website accessibility guide.
Fix the common offenders first
The same few patterns cause most failures:
- Light gray text on white (captions, dates, metadata)
- Placeholder text in form fields
- White text on light or mid-tone buttons
- Light-colored links
- Faint borders on inputs and buttons (these fall under 1.4.11)
- Footer text on a colored background
Text on images
Text placed over a photo or gradient is hard to test because the background changes behind every letter. Approaches that work:
- Add an overlay. A solid or semi-transparent dark layer between the image and the text gives a predictable background. Test against the lightest part of the image behind the text, since that is the worst case.
- Put text on a solid panel. A colored box behind the heading removes the problem entirely.
- Move the text. Place it over a calmer area of the image, or beside it.
- Choose images with consistent tone in the area where text sits.
.hero::before {
content: "";
position: absolute;
inset: 0;
background: rgba(0, 0, 0, 0.55);
}
.hero__title { position: relative; color: #ffffff; }
A text shadow alone is not a reliable fix, because contrast tools and the WCAG measurement do not treat it as changing the background.
Text that is part of an image, such as a banner with a promotion baked in, needs sufficient contrast within the image itself. It also needs a text alternative; see WCAG 1.1.1 Non-text Content. Where possible, use real HTML text instead of text in images.
When your brand colors fail
Brand palettes are often built for print or logos, not for text on screens. The usual failures are a light brand color used for links, or white text on a mid-tone brand button. You can usually keep the brand without failing.
Keep the brand, change how it's used
- Use the brand color as a background, with dark or white text that passes. If white on your brand orange fails, try near-black text on the orange instead.
- Use the brand color for large text and decoration, where the lower 3:1 threshold applies, and use a darker shade for body-size text and links.
- Create an accessible shade. Keep the same hue and darken (or lighten) it until it passes. A slightly deeper version of your brand blue is still recognizably your blue.
- Define a small set of approved pairings, for example "brand-orange on near-black" and "white on dark-brand-orange," and use only those for text.
What about logos?
WCAG exempts logos and brand names from the text contrast requirement. That means you do not need to alter your logo. It does not exempt the rest of your design.
A practical way to record this is to add accessible variants to your palette:
:root {
--brand-orange: #f26b21; /* decoration, large text on dark */
--brand-orange-text: #b84a0c; /* body-size text and links on white */
}
A repeatable process
- Pull every color your site uses into a list, ideally from your theme variables.
- Test each text and background pairing against 4.5:1 or 3:1 as appropriate.
- Fix failing variables once, centrally.
- Re-scan key templates and check hover, focus, and error states.
- Manually review text on images.
- Record what you tested and when. A dated accessibility audit record shows the work you did and when you did it.
Contrast is one item among many. The WCAG 2.1 AA checklist covers the rest, and WCAG 2.2 vs 2.1 explains how the newer version relates. If you want a starting point, run a free scan to see which contrast failures show up first.
Frequently asked questions
What contrast ratio do I need for WCAG 2.1 AA?
Normal text needs at least 4.5:1 against its background. Large text (18 point or larger, or 14 point bold or larger) needs at least 3:1. User interface components such as input borders, and graphics needed to understand content, also need 3:1.
Can I fix contrast without changing my brand colors?
Often yes. You can keep the brand color for backgrounds, large text, and decoration, and use a slightly darker shade of the same hue for body-size text and links. Logos are exempt from the text contrast requirement, so the logo itself does not need to change.
Do automated tools catch all contrast problems?
No. They catch many failures on solid backgrounds but are weak on text over images, gradients, text inside images, and states that appear only on hover or focus. Pair an automated scan with a manual review of those areas.
Does passing a contrast checker make my site compliant?
No. Contrast is only one part of WCAG, and no single check or tool can make a site compliant. Treat it as one item in a broader review, and ask an attorney about any legal questions.
Is a text shadow or outline enough to meet contrast requirements?
Generally you should not rely on it. WCAG contrast is measured between the text color and its background, and a shadow does not reliably change that measurement. A solid panel or overlay behind the text is a safer fix.
Related
- WCAG 2.1 AA checklist for business websites
- WCAG 1.4.3 Contrast (Minimum)
- WordPress Accessibility: Themes, Plugins and What to Check
- Why a dated accessibility audit record matters
Proof of Access provides technical accessibility assessments. We are not a law firm and nothing on this page is legal advice. If you have received a demand letter or a lawsuit, talk to an attorney.