Colors

Color Accessibility: WCAG Contrast Guidelines

Making your designs accessible: understanding WCAG contrast ratios, testing for accessibility, and designing for color blindness.

HandyUtils December 29, 2025 6 min read

Color accessibility isn't just a nice-to-have—it's essential for creating inclusive websites. About 8% of men and 0.5% of women have some form of color vision deficiency. Add in users with low vision, situational impairments (bright sunlight), and aging eyes, and accessible color choices matter for everyone.

Why Color Accessibility Matters

Poor color contrast affects:

  • 300+ million people with color blindness worldwide
  • 2.2 billion people with vision impairment
  • Everyone using devices in bright sunlight
  • Users with aging eyes (contrast sensitivity decreases with age)
  • Anyone with temporary eye strain

Beyond ethics, there are legal requirements. Many countries mandate web accessibility, and lawsuits over inaccessible websites are increasing.

WCAG Contrast Requirements

The Web Content Accessibility Guidelines (WCAG) define contrast ratio requirements:

Contrast Ratio Formula

The contrast ratio compares the luminance of two colors:

Contrast Ratio = (L1 + 0.05) / (L2 + 0.05)

Where L1 is the lighter color's luminance and L2 is the darker.

Ratios range from 1:1 (no contrast) to 21:1 (black on white).

WCAG Levels

Level AA (Minimum)

  • Normal text: 4.5:1 minimum
  • Large text (18pt+ or 14pt bold): 3:1 minimum
  • UI components/graphics: 3:1 minimum

Level AAA (Enhanced)

  • Normal text: 7:1 minimum
  • Large text: 4.5:1 minimum

Most organizations target Level AA as a baseline.

Understanding Contrast Ratios

Ratio Example Use Accessibility
21:1 Black on white Excellent
7:1 Dark gray on white AAA for normal text
4.5:1 Medium gray on white AA for normal text
3:1 Large headings, UI elements AA minimum
2:1 Decorative text Fails most requirements
1:1 Same color No contrast

Examples with Ratios

/* Excellent contrast (21:1) */
color: #000000;           /* Black text */
background: #FFFFFF;      /* White background */

/* Good contrast (~7:1) */
color: #333333;           /* Dark gray text */
background: #FFFFFF;      /* White background */

/* Borderline AA (~4.5:1) */
color: #767676;           /* Medium gray */
background: #FFFFFF;      /* White background */

/* Fails for body text (~3:1) */
color: #959595;           /* Light gray - avoid for small text */
background: #FFFFFF;

Testing Contrast Ratios

Manual Testing Tools

  1. Browser DevTools: Chrome's color picker shows contrast ratios
  2. Online checkers: WebAIM Contrast Checker, our Contrast Checker tool
  3. Design tools: Figma, Sketch plugins

Automated Testing

// Calculate relative luminance
function getLuminance(r, g, b) {
    const [rs, gs, bs] = [r, g, b].map(c => {
        c = c / 255;
        return c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
    });
    return 0.2126 * rs + 0.7152 * gs + 0.0722 * bs;
}

// Calculate contrast ratio
function getContrastRatio(color1, color2) {
    const l1 = getLuminance(...color1);
    const l2 = getLuminance(...color2);
    const lighter = Math.max(l1, l2);
    const darker = Math.min(l1, l2);
    return (lighter + 0.05) / (darker + 0.05);
}

// Example
const ratio = getContrastRatio([0, 0, 0], [255, 255, 255]); // 21

Common Contrast Mistakes

1. Light Gray Text

/* Too low contrast for body text */
color: #999999;  /* 2.85:1 on white - FAILS */

/* Better */
color: #767676;  /* 4.54:1 on white - PASSES AA */

2. Placeholder Text

Placeholder text often uses very light colors:

/* Default browser placeholders often fail */
::placeholder {
    color: #a0a0a0;  /* Often fails */
}

/* Better */
::placeholder {
    color: #767676;  /* 4.5:1 minimum */
}

3. Disabled States

Disabled elements still need to be readable:

/* Often too light */
.button:disabled {
    color: #cccccc;  /* FAILS */
}

/* Keep it readable even when disabled */
.button:disabled {
    color: #767676;
    cursor: not-allowed;
}

Links need to be distinguishable from surrounding text by more than just color:

/* Add underline or other visual indicator */
a {
    color: #0066cc;
    text-decoration: underline;  /* Don't rely on color alone */
}

Color Blindness Types

Red-Green Color Blindness (Most Common)

Deuteranopia/Deuteranomaly (~6% of males):

  • Difficulty distinguishing red from green
  • Greens may look brownish

Protanopia/Protanomaly (~2% of males):

  • Reds appear darker, sometimes black
  • Difficulty with red-green distinction

Blue-Yellow Color Blindness (Rare)

Tritanopia/Tritanomaly (<1%):

  • Blues may appear greenish
  • Yellows may appear pink

Complete Color Blindness (Very Rare)

Achromatopsia (~0.003%):

  • Sees only grayscale
  • Very sensitive to light

Designing for Color Blindness

1. Don't Rely on Color Alone

<!-- Bad: Status shown only by color -->
<span class="status-red">Error</span>
<span class="status-green">Success</span>

<!-- Good: Icons and text reinforce meaning -->
<span class="status-error">
    <i class="icon-error"></i> Error: Invalid email
</span>
<span class="status-success">
    <i class="icon-check"></i> Success: Saved
</span>

2. Use Patterns in Charts

/* Don't just vary hue */
.chart-series-1 { fill: red; }
.chart-series-2 { fill: green; }

/* Add patterns for distinction */
.chart-series-1 { fill: url(#pattern-dots); }
.chart-series-2 { fill: url(#pattern-lines); }

3. Choose Color-Blind-Friendly Palettes

Avoid problematic combinations:

  • ❌ Red/Green
  • ❌ Blue/Purple
  • ❌ Green/Brown
  • ❌ Light green/Yellow

Better combinations:

  • ✅ Blue/Orange
  • ✅ Blue/Yellow
  • ✅ Purple/Yellow
  • ✅ Different values (light vs dark) of any color

4. Test with Simulators

Use color blindness simulators to check your designs:

  • Browser extensions (e.g., Colorblindly)
  • Design tool plugins
  • Our Color Blindness Simulator tool

Tools for Accessibility Testing

Browser DevTools

Chrome DevTools:

  1. Inspect element
  2. Click the color swatch
  3. See contrast ratio in the picker

Automated Tools

# axe-core for automated testing
npm install axe-core

# lighthouse
npx lighthouse https://yoursite.com --only-categories=accessibility

Manual Testing

  1. Squint test: Blur your vision—can you still read?
  2. Grayscale test: View in grayscale—is meaning preserved?
  3. Zoom test: Does it work at 200% zoom?

Beyond Color: Other Accessibility Concerns

Focus Indicators

/* Don't remove focus outlines! */
:focus {
    outline: 2px solid #0066cc;
    outline-offset: 2px;
}

/* Style them to match your design instead */
button:focus {
    box-shadow: 0 0 0 3px rgba(0, 102, 204, 0.5);
}

Text Sizing

  • Use relative units (rem, em) not px
  • Don't disable zoom
  • Ensure line height is at least 1.5

Motion

/* Respect user preferences */
@media (prefers-reduced-motion: reduce) {
    * {
        animation: none !important;
        transition: none !important;
    }
}

Summary

Color accessibility requires:

  1. Sufficient contrast: 4.5:1 for text, 3:1 for large text/UI
  2. Not color alone: Use icons, text, patterns alongside color
  3. Color-blind-friendly palettes: Avoid red/green, test with simulators
  4. Test your work: Use automated tools and manual testing

Accessibility benefits everyone—it's not just about compliance, it's about inclusion.

Need to check your color contrast? Try our Contrast Checker or Color Blindness Simulator!

Related Topics
accessibility wcag contrast ratio color blindness a11y inclusive design
Share this article

Continue Reading

Colors
Web Colors Explained: HEX, RGB, and HSL

Understanding color formats for web development: when to use HEX vs RGB vs HSL, color spaces, and practical tips for choosing colors.

Colors
Creating Color Palettes: Harmony and Theory

Learn the fundamentals of color theory to create beautiful, harmonious palettes for your designs using color wheel relationships.

Number Systems
Hexadecimal for Developers: Colors, Memory, and More

A practical guide to hexadecimal notation: why developers use hex, reading hex values, and everyday applications from color codes to debugging.