Skip to content
Back to Blog
Tutorials

WCAG Color Contrast Ratio Guide: AA, AAA, and APCA Explained

Master WCAG contrast ratios. Learn 4.5:1 AA and 7:1 AAA thresholds, the APCA Lc algorithm, color blindness, and how to fix failing combinations.

15 min read

WCAG Color Contrast Ratio: AA, AAA & APCA — The Complete 2026 Guide

You ship a button without checking the WCAG contrast ratio. Brand orange, white text, looks crisp on your 4K monitor. Then an accessibility audit comes back red: the contrast ratio for that button is 1.97:1, nowhere near the 4.5:1 AA threshold for body text. The button that looked fine to you is unreadable to roughly 220 million people with low vision worldwide. This guide walks through every number you need to fix that: WCAG 2 ratios, the AAA tier, the new APCA Lc algorithm, eight categories of color vision deficiency, and a working JavaScript implementation you can drop into your build.

Quick reference: WCAG and APCA thresholds at a glance

StandardNormal textLarge textUI / iconsNotes
WCAG AA≥ 4.5:1≥ 3:1≥ 3:1Legal baseline
WCAG AAA≥ 7:1≥ 4.5:1≥ 3:1Enhanced target
APCA bodyLc 75+Lc 60+Lc 45+ (icons)Draft, perceptual

“Large text” means ≥ 18pt regular or ≥ 14pt bold (≈ 24px and ≈ 18.66px in CSS). “UI” covers form borders, focus rings, and any graphical object a user must perceive to operate the page. Logos and purely decorative graphics are exempt from contrast requirements.

What is WCAG color contrast?

WCAG contrast ratio is a numeric measure from 1:1 (no contrast) to 21:1 (maximum) comparing the relative luminance of text against its background. The Web Content Accessibility Guidelines require ≥ 4.5:1 (AA) for body text or ≥ 7:1 (AAA) for enhanced compliance.

That single ratio drives most accessibility audits worldwide. The W3C published it in WCAG 2.0 back in 2008, refined it in 2.1 (2018) and 2.2 (2023), and every major regulator now points at it. The ADA in the United States, the European Accessibility Act (which became enforceable in June 2025), Section 508 for U.S. federal agencies, and Canada’s AODA all use WCAG 2.x AA as their de facto floor.

Why does any of this matter past the legal angle? Roughly 220 million people worldwide have low vision but are not blind. They read screens, but only when the type/background contrast is high enough. Around 8% of men and 0.5% of women have a color vision deficiency. Older readers experience yellowing of the lens and reduced pupil aperture, which functionally lowers perceived contrast by 20–30% after age 60. Outdoor smartphone use loses another 20–40% to glare. A page that scores 4.5:1 on your desk is the floor at which all of those users can still read it.

The people who need to care most are front-end engineers shipping production UI, designers picking brand palettes, accessibility specialists running audits, and compliance teams responsible for legal exposure. The math is short. The decisions it forces are not.

WCAG 2.x contrast ratio: the math, the thresholds

The W3C defines contrast in three short steps. To calculate WCAG contrast ratio: (1) convert each color from gamma-encoded sRGB to linear-light values, (2) compute the relative luminance using fixed coefficients for the human eye’s sensitivity to red, green, and blue, and (3) divide the two luminances with a small constant offset to handle near-black values.

The relative luminance formula from WCAG 2.1 §1.4.3 is:

L = 0.2126 × R_lin + 0.7152 × G_lin + 0.0722 × B_lin

R_lin, G_lin, B_lin are the linear-light channel values after un-doing the sRGB gamma curve. The 0.7152 weighting on green reflects the human eye’s strong green sensitivity: green is roughly 7× louder than blue per unit of light energy.

The ratio formula is:

ratio = (L_lighter + 0.05) / (L_darker + 0.05)

The +0.05 prevents division-by-zero for pure black (L = 0) and gives a maximum of (1 + 0.05) / (0 + 0.05) = 21:1 for pure white on pure black. The minimum is 1:1 (identical colors).

Here is the full implementation in roughly thirty lines of vanilla JavaScript. No dependencies, runs anywhere:

// sRGB hex → linear-light channel
function srgbToLinear(channel8bit) {
  const v = channel8bit / 255;
  return v <= 0.04045 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);
}

// "#RRGGBB" → relative luminance [0, 1]
function relativeLuminance(hex) {
  const h = hex.replace("#", "");
  const r = parseInt(h.slice(0, 2), 16);
  const g = parseInt(h.slice(2, 4), 16);
  const b = parseInt(h.slice(4, 6), 16);
  return (
    0.2126 * srgbToLinear(r) +
    0.7152 * srgbToLinear(g) +
    0.0722 * srgbToLinear(b)
  );
}

// WCAG 2.x contrast ratio between two hex colors
function contrastRatio(hexA, hexB) {
  const lA = relativeLuminance(hexA);
  const lB = relativeLuminance(hexB);
  const [lighter, darker] = lA > lB ? [lA, lB] : [lB, lA];
  return (lighter + 0.05) / (darker + 0.05);
}

// Sample: dark slate body text on white
console.log(contrastRatio("#475569", "#ffffff").toFixed(2));
// → "7.58" — comfortably above AA 4.5:1 and just over AAA 7:1

Drop two hex codes into the Color Converter and the same numbers come back, rendered alongside an APCA Lc value, a gamut classification, and an eight-channel CVD preview. The thresholds themselves are concrete:

ElementAA minAAA minNotes
Normal body text4.5:17:1Under 18pt regular / under 14pt bold
Large text3:14.5:1≥ 18pt regular OR ≥ 14pt bold
UI components / icons3:1WCAG 2.1 §1.4.11 added in 2018
Logos & decorativeexemptexemptNo contrast requirement

The CSS unit conversions trip people up. 18pt = 24px at the browser default, 14pt = 18.66px. A 16px body font (the modern default) is below the “large text” threshold, so it falls under the stricter 4.5:1 AA rule. A 20px heading at font-weight: 700 qualifies as large and gets the looser 3:1.

One subtlety that catches teams off-guard: WCAG’s “large text” exemption is about user readability at scale, not about heading semantics. A 14px <h2> is not large text; it still needs 4.5:1. A 24px paragraph of marketing copy is large text and gets the 3:1 floor. The rule keys on rendered pixel size and weight, never on tag name. Auditors will flag mismatches; your CSS is the source of truth, not your HTML semantics.

The +0.05 constant in the ratio formula has a specific origin: it represents the flare term, the ambient light reflected off the screen surface that lifts the apparent luminance of pure black up to a minimum floor. Without it, an OLED pixel rendering true black against pure white would give a divide-by-zero. With it, the maximum achievable ratio is 21:1, a number you’ll see called out in every accessibility tool. There is no physical screen that can deliver more than 21:1 once flare is accounted for, which is why the WCAG scale tops out there.

AA vs AAA: which should you target?

AA is the legal floor; AAA is the aspirational tier. Most commercial sites target AA because AAA forces brand colors toward grayscale to pass, which most marketing teams refuse to do. The decision is not “more is better”; it’s a tradeoff between user reach and brand expression.

ContextRecommended tierWhy
General commercial siteAAADA / EAA compliance baseline; courts cite WCAG 2 AA
Government / public servicesAAASection 508 and equivalent EU statutes recommend AAA
Healthcare / educationAAAUser base skews toward higher accessibility needs
Internal dashboardAAKnown audience, ROI tradeoff acceptable
Marketing landing pageAA + brand carve-outBrand colors allowed on hero/CTAs, body still AA

The hidden cost of AAA shows up the first time you try to make a saturated brand orange pass 7:1 against white. It can’t. You either darken the orange until it stops being your brand, or you accept AA and use the orange on dark backgrounds where it can hit AAA easily. Plenty of companies, including some of the more accessibility-conscious ones, explicitly target AA on body content and only push for AAA on critical text like error messages or legal disclosures.

Regulators have not waited for AAA to spread. The ADA’s 2024 web-accessibility regulation cites WCAG 2.1 AA. The European Accessibility Act, enforceable since June 2025, requires WCAG 2.1 AA across covered digital services. Section 508 in the U.S. federal government uses WCAG 2.0 AA as its baseline (with AAA recommended where feasible). Canada’s AODA, Ontario’s accessibility statute, points to WCAG 2.0 AA. The pattern is consistent: AA is the bar, AAA is the goal.

APCA: the new perceptual algorithm

APCA (the Advanced Perceptual Contrast Algorithm, designed by Andrew Somers under the Myndex label) is a candidate algorithm for WCAG 3. It replaces WCAG 2’s symmetric ratio with a polarity-signed Lc score from -108 to +108, where the sign tells you which direction the contrast runs (dark text on light vs light text on dark) and the magnitude reflects perceived contrast on a real emissive display.

APCA matters because WCAG 2’s symmetric formula misses two real-world effects:

  • Polarity asymmetry. Light text on a dark background reads differently from dark text on a light background, even at the same WCAG ratio. WCAG 2 returns the same number for both directions; APCA does not.
  • Display modeling. WCAG 2’s formula was derived from print-paper luminance models. APCA was tuned against sRGB displays in typical office lighting, which is closer to what your users actually see.

The trade-off: APCA is more complex (it involves polarity-aware exponents and font-weight adjustments) and it is not yet a regulatory standard. Adrian Roselli’s April 2026 analysis remains the clearest summary of where APCA sits: technically promising, but WCAG 3 itself is still in early-draft Silver-track development, and APCA has not been ratified as the official algorithm yet.

The APCA Bronze-level thresholds (the practical floor most teams target) look like this:

Use caseRecommended LcMinimum Lc
Body text (16px, weight 400)90+75
Large text (24px, weight 400)75+60
UI elements & non-text icons60+45
Spot text / placeholders30+30

The reason APCA is interesting (and the reason the Color Converter surfaces both metrics side by side) is the cases where it disagrees with WCAG 2:

  • #FFA500 (orange) on #FFFFFF: WCAG 2 returns 1.97:1, a clear fail at AA. APCA agrees, scoring around Lc 38, also a fail. Both algorithms say no, yet most designers I’ve watched still ship this combination because “it looks fine.”
  • #767676 (mid-gray) on #FFFFFF: WCAG 2 returns 4.54:1, just over AA 4.5:1, technically a pass. APCA scores this pair at approximately Lc 60, which is below APCA Bronze’s 75 threshold for body text. WCAG passes; APCA fails. The user’s lived experience is closer to APCA’s verdict: that gray on white is harder to read at body sizes than the ratio suggests.
  • #3b82f6 (Tailwind blue-500) on #000000: WCAG 2 returns 5.71:1, a comfortable AA pass. APCA scores this around Lc 65, below the body-text Lc 75 minimum. Light blue text on a dark background, a beloved dark-mode pattern, is the canonical “WCAG passes, APCA flags” case.

You don’t have to pick a side. The pragmatic stance most production teams have settled on: keep WCAG 2 AA as the regulatory baseline because it’s what compliance audits check against, and run APCA in parallel as a “is this actually readable?” gut check, especially for dark-mode designs and saturated brand colors. The Color Converter shows both numbers in one row so you don’t have to context-switch between checkers.

Color blindness and beyond contrast

Contrast ratios are only half of color accessibility. Around 8% of men and 0.5% of women see colors differently from the textbook trichromat, and the most common variant, deuteranomaly, sits in the middle of the red/green pair we use everywhere for success/error states. WCAG 1.4.1 (“Use of Color”) explicitly bans color as the sole carrier of information; this is the rule it exists to enforce.

The full taxonomy of color vision differences breaks into three groups: dichromacy (one cone missing), anomalous trichromacy (one cone shifted), and the rare monochromacies.

TypeCommon nameAffected channelPrevalence (M / F)
ProtanopiaRed-blindL cone absent1.0% / 0.01%
DeuteranopiaGreen-blindM cone absent1.1% / 0.01%
TritanopiaBlue-blindS cone absent0.003% / 0.003%
ProtanomalyRed-weakL cone shifted1.3% / 0.02%
DeuteranomalyGreen-weakM cone shifted5.0% / 0.4%
TritanomalyBlue-weakS cone shifted0.01% / 0.01%
AchromatopsiaNo colorAll cones absent0.003% (very rare)
Cone monochromacyPartial grayOne cone only0.001%

Deuteranomaly alone is 5% of men: one in twenty. That’s the population that sees a red error indicator and a green success indicator as nearly the same olive-brown hue. The fix is not to redesign your color system; it’s to add a second channel. A red error icon paired with an ”×” shape and the word “Error” survives every variant in the table. A bare red dot does not.

Simulating CVD in code uses two standard matrix sets: Brettel–Viénot–Mollon (1997) for the dichromacies and Machado–Oliveira–Fernandes (2009) for the anomalous trichromacies. The Brettel approach projects the user’s input color onto a plane spanned by the two remaining cone responses; Machado parameterizes the cone shift by severity. Both are implementable as SVG filters or CSS matrices. The Color Converter ships all eight variants as one-click previews so you can scan a brand color across the spectrum without leaving the page.

A short SVG filter, dropped into your page and referenced by ID, gives you in-browser protanopia simulation for ad-hoc testing:

<svg style="display: none">
  <filter id="protanopia">
    <feColorMatrix type="matrix" values="
      0.567 0.433 0.000 0 0
      0.558 0.442 0.000 0 0
      0.000 0.242 0.758 0 0
      0.000 0.000 0.000 1 0"/>
  </filter>
</svg>

<style>
  .preview-protanopia { filter: url(#protanopia); }
</style>

Apply .preview-protanopia to your page wrapper to see what a protanope sees. Repeat with the deuteranopia and tritanopia matrices (their coefficients are documented in the Brettel paper, and bundled in most CVD simulator libraries). Chrome DevTools’ Rendering panel has the same simulators built in under “Emulate vision deficiencies”, useful for quick checks, less useful for capturing screenshots in CI.

One rule sits beneath all the simulation work: never let color be the only difference between two states. Icons should differ in shape (× vs ), states in text label (“Error” vs “Success”), categories in pattern (solid vs hatched). Color is a multiplier on those other signals, not a substitute.

There’s a class of failures that contrast checkers don’t catch but CVD simulators do. Pie chart segments distinguished only by hue, map legends that color-code countries, status pills that rely on a green/yellow/red gradient: all of them can clear WCAG 2 contrast against the background while being unreadable to a deuteranope reading them against each other. The rule is to check legibility between adjacent colors in the design, not just against the surrounding canvas. Two slate-500 segments next to each other at the same lightness are indistinguishable regardless of hue rotation. Add a luminance step between adjacent regions and the chart survives every CVD variant.

Achromatopsia and cone monochromacy are rare but worth designing for explicitly because they collapse all hue distinctions. A user with achromatopsia perceives only luminance; your color-coded UI looks like a grayscale photograph to them. If your design holds up when you run a filter: grayscale(1) over the whole page (try it in DevTools), you’ve passed the strictest version of the “color is not the only signal” rule. It’s the cheapest accessibility test you can run, and it surfaces a surprising number of failures the moment you toggle it.

Auditing Tailwind and Material palettes

Most front-end work uses a pre-built palette: Tailwind v4, Material 3, Radix, or shadcn. The accessibility question becomes “at which stop of this ramp does the text become readable?”, and the answer is more rule-of-thumb than the docs admit.

For Tailwind v4’s slate ramp against pure white, the WCAG and APCA numbers fall like this:

Tailwind classApprox hexWCAG vs whiteAA bodyAAA bodyAPCA Lc (approx)
slate-400#94a3b82.56:1~38 ✗
slate-500#64748b4.76:1~60 ✗ body
slate-600#4755697.58:1~78 ✓ body
slate-700#33415510.35:1~90 ✓ body

The practical rules that fall out:

  • Body text needs slate-600 or darker. Slate-500 passes WCAG AA but fails APCA’s body-text threshold, so it’s compliant but uncomfortable. Slate-600 is the safe floor.
  • UI labels and secondary text can use slate-500. UI components only need 3:1; the 4.76:1 from slate-500 is comfortable, and the text usually carries supporting visual context.
  • Placeholders should use slate-400 or fade lighter. Placeholder text is WCAG 1.4.3-exempt as decorative only if you keep a visible label above the field. Inline-label-as-placeholder patterns must hit the body-text threshold.
  • Pure black on slate-100 / slate-200 is wasted ink. You’re at 17:1+; consider using slate-700 or slate-800 as the text color for a softer feel without losing readability.

Material 3 uses a similar tonal palette structure. Its surface-container-high lives around tone 92 (very light); its on-surface lives around tone 10 (near-black). The contrast between any on-surface and any surface-* token in the same family is guaranteed by Material’s spec to clear AA. Don’t pair on-surface-variant (tone 30) against surface-container (tone 94) without checking; that’s a real-world miss I’ve seen ship.

If you have an existing palette that fails contrast, OKLCH gives you the cleanest fix path. Instead of nudging hex codes blindly, convert your color to OKLCH, hold C (chroma) and H (hue) fixed, and reduce L (lightness) until the contrast passes. Because OKLCH’s L channel is genuinely perceptual, the brand recognition stays intact while the contrast tightens. The HEX to OKLCH tool does this conversion in one step; the OKLCH explained sister post covers the math in depth.

Dark mode deserves its own treatment. WCAG 2’s symmetric ratio passes the same combinations in light and dark mode by definition. APCA, being polarity-aware, frequently flags dark-mode body text as harder to read than the same hex pair would be in light mode. Light-on-dark always loses some perceived contrast relative to dark-on-light at the same numeric ratio; it’s a known effect of how the eye adapts. Re-run APCA on every dark-mode pair before shipping.

Contrast checkers and CI workflows

Designers and engineers each have a favorite checker; the practical question is which combination of tools you stitch into a real workflow. Here is the field as of 2026:

ToolWCAG 2APCACVD simPalette audit
WebAIM Contrast Checker
Adobe Color
Stark (Figma plugin)
Polypane (browser)
Chrome DevTools color picker✓ (exp.)
axe DevTools✓ (page-level)
Go Tools Color Converter✓ (8 types)✓ (Tints/Shades)

A workflow that holds up under real product pressure looks like this:

  1. In Figma, designers run Stark on each frame to surface failing pairs early. Stark catches the obvious offenders before any hex code reaches the codebase.
  2. At hex-code handoff, engineers paste the value into the Color Converter to get WCAG ratio + APCA Lc + gamut classification + CVD preview in one row. If the pair is dark-mode or saturated-brand, the dual metric catches the WCAG-passes-APCA-fails cases Stark might miss.
  3. At PR time, axe-core/playwright scans the built pages for any contrast violation on the rendered DOM, including dynamic states. This catches focus rings, hover states, and disabled affordances that static design files miss.
  4. In QA, Chrome DevTools’ Rendering tab simulates protanopia/deuteranopia/tritanopia for spot checks on critical flows. The Color Picker in DevTools also surfaces a WCAG ratio inline when you hover any element.

Pa11y, Lighthouse CI, and @axe-core/playwright all expose contrast assertions as part of their broader accessibility audits. None of them check APCA today; they all check WCAG 2. The realistic compromise is “enforce WCAG 2 AA in CI, sanity-check APCA Lc manually for brand colors and dark mode.”

A pattern worth borrowing from larger design-system teams: bake the contrast check into your token validation step, not just into page-level QA. If your design tokens compile from a source file (JSON, YAML, or a TypeScript module), add a script that enumerates every --text-* × --surface-* pairing the system allows and asserts a minimum WCAG ratio. The script runs in milliseconds, catches regressions when someone tweaks a token value, and produces a contrast matrix that doubles as documentation for the design team. The check is independent of any rendered page; it operates purely on the tokens, so it catches the failure before any UI ships.

For ad-hoc conversions during this workflow (converting between hex, RGB, HSL, and OKLCH while you debug), the HEX to RGB, HEX to HSL, HEX to OKLCH, and RGB to HEX spokes cover round-trips into and out of any color format your toolchain expects.

Common mistakes and how to fix them

After years of accessibility audits, the same six failures keep showing up. Each has a tidy fix:

  1. Placeholder text in light gray. #999999 on white is 2.85:1, fails AA. Either deepen to #666666 (5.74:1, passes AA) or, better, replace placeholder-as-label patterns with a persistent visible label above the field. Placeholders should not carry information.

  2. Brand orange button with white text. #FFA500 on white is 1.97:1, fails AA badly. The fix that preserves brand is to invert the contrast direction: dark text (e.g. #451a03) on the orange background, or keep the white text but darken the button to a deep saturated brown-orange. Verify in the Color Converter before shipping.

  3. Bright blue link in dark mode. #3b82f6 on #000000 is 5.71:1, a WCAG AA pass, but APCA Lc ~65, below the Lc 75 body threshold. Reach for OKLCH and bump L from ≈ 0.63 to 0.75, holding C and H fixed; you’ll land near #7aa5f8 with a comfortable APCA Lc 80+ and the same hue.

  4. Disabled text in #CCCCCC. 1.61:1 against white. WCAG 1.4.3 exempts purely decorative text from the ratio rule, but disabled UI controls are not decorative; they communicate “this is currently unavailable.” Pair the muted color with a non-color cue (strikethrough, lock icon, “Disabled” tooltip) so a CVD or low-vision user still understands the state.

  5. Status icons that differ only in hue. A red × and a green is fine because the shape already distinguishes them. A red dot vs a green dot is not. Use shape and color together; the Color Converter’s CVD preview makes the failure case obvious in a second.

  6. Text over a gradient background. A gradient that runs from #3b82f6 to #a78bfa against white text passes contrast in the middle and fails near the lavender end. The fix is to enforce the contrast against the worst-case point of the gradient, or to overlay a semi-transparent dark scrim so the effective background luminance is always under a known threshold.

Each fix takes minutes. The audit cycle they avoid takes weeks.

FAQ

What is WCAG AA contrast ratio?

WCAG AA requires ≥ 4.5:1 between body text and background, or ≥ 3:1 for large text (≥ 18pt regular or ≥ 14pt bold) and UI components like form borders. AA is the legal baseline under ADA, EAA, and Section 508. Most commercial sites target AA because it covers the regulatory bar without forcing brand colors toward grayscale.

What contrast ratio do I need for AAA?

WCAG AAA requires ≥ 7:1 for normal body text and ≥ 4.5:1 for large text. AAA is recommended for medical, educational, and government sites where the user base skews toward higher accessibility needs. Brand colors often need flattening toward grayscale-adjacent values to pass AAA, which is why many commercial products stop at AA.

What is APCA and is it WCAG 3.0?

APCA (Advanced Perceptual Contrast Algorithm), designed by Andrew Somers / Myndex, is a candidate algorithm under the WCAG 3 Silver project. It uses polarity-sensitive Lc scores from -108 to +108 instead of symmetric ratios. WCAG 3 is still in early draft and APCA has not been formally ratified. WCAG 2.1 / 2.2 AA remains the regulatory standard you must hit today.

Does dark mode help contrast accessibility?

Sometimes, but not automatically. WCAG 2’s symmetric ratio passes the same combinations in light and dark mode, but APCA (which is polarity-sensitive) often flags dark-mode body text as harder to read than the same hex pair in light mode. Always re-test dark mode against both WCAG and APCA before shipping; light-on-dark loses perceived contrast in ways the symmetric ratio cannot see.

Why does my brand color fail WCAG AA?

Saturated mid-luminance colors (most oranges, yellows, lime greens, light blues) have relative luminance values too close to white to clear 4.5:1. The fix: keep the brand hue for accents and large headlines, but pair body text with a darker tone from the same hue family. Use OKLCH to lower the L channel without shifting hue. The Color Converter finds the closest passing shade in one step.

Are WCAG 2 ratios and APCA scores compatible?

No. WCAG 2 returns a symmetric ratio (1–21); APCA returns a polarity-signed Lc score (-108 to +108). The relationship is non-linear: a pair that’s 4.5:1 in WCAG might score Lc 60 or Lc 75 in APCA depending on which color is on top. Treat them as two independent checks, not as translations of one another.

Can I use color contrast for small UI icons?

Yes, with caveats. WCAG 2.1 §1.4.11 requires ≥ 3:1 for UI components and graphical objects. For decorative icons paired with a visible text label, contrast requirements relax because the label carries the meaning. For stand-alone icons (e.g., a search magnifier with no label), enforce the full 3:1 against the surrounding background.

How do I test color blindness without simulating?

Use Chrome DevTools → Rendering → “Emulate vision deficiencies” for protanopia, deuteranopia, tritanopia, and achromatopsia. Combine with the Color Converter’s 8-type CVD preview for the anomalous trichromacy variants (deuteranomaly being the most common at 5% of men). For audit reporting, capture screenshots under each simulation so reviewers can see the failure modes inline.

Is 4.5:1 contrast ratio enough for accessibility?

Yes — for normal body text on standard commercial sites. The 4.5:1 WCAG contrast ratio is the AA threshold for body text under 18pt regular / 14pt bold. Government, medical, and educational sites should target AAA (7:1). Anything below 4.5:1 fails accessibility audits and ADA compliance baselines.

Conclusion

Five takeaways carry the whole guide:

  • AA 4.5:1 is the legal floor. Hit it for all body text or expect compliance noise.
  • AAA 7:1 is for healthcare, education, and government. Most commercial brands stop at AA by design.
  • APCA Lc is the real-readability sanity check. Run it in parallel with WCAG 2, especially for dark mode and saturated brand colors.
  • Color is never the only signal. Pair every color cue with shape, text, or pattern. Deuteranomaly alone is 5% of male users.
  • OKLCH L is the right knob. When a color fails contrast, reduce L (not S, not B) to fix it without drifting hue.

Drop any two hex codes into the Color Converter to see WCAG ratio, APCA Lc, gamut classification, and the 8-type CVD preview side by side. That single view replaces six separate tools and is the fastest way to close out the audits this guide describes.

Related Articles

View all articles