Hit space. Get colors that actually pass.
Five swatches. Locked or fresh. Spacebar to regenerate, click the lock to keep one. The URL is the database, so a paste into Slack is a full save.
Pair preview: 14 · 18.66 · UI
A live preview of this palette on something real: heading, body, an inline link, a button, a chip.
Normal text needs a 4.5:1 contrast ratio to clear WCAG AA, large text only 3:1, and APCA scores the same pair differently depending on which color sits on top. Those thresholds, plus the data they rest on, are collected here: the contrast minimum each standard sets by context, the APCA Lc readability levels, color vision deficiency prevalence, the OKLCH channel ranges the generator draws from, and the exact syntax of every token format the tool exports.
WCAG 2.1 contrast minimums by context
WCAG sets a different minimum ratio depending on text size, text weight, and whether the element is text or a non-text control.
| Element / context | AA minimum | AAA minimum | Success Criterion |
|---|---|---|---|
| Normal text (below 24px, or below 18.66px bold) | 4.5:1 | 7:1 | 1.4.3 / 1.4.6 |
| Large text (24px+, or 18.66px+ bold) | 3:1 | 4.5:1 | 1.4.3 / 1.4.6 |
| UI components and graphical objects | 3:1 | n/a | 1.4.11 |
| Disabled controls, pure decoration, logotypes | none | none | exempt |
Large text is 18pt (24px) at a regular weight, or 14pt (18.66px) at bold. The ratio always divides the brighter relative luminance by the darker, so it reads the same regardless of which color is the foreground.
APCA Lc levels and intended use
APCA reports a polarity-signed lightness contrast (Lc) that runs from about -108 to 106; Shadl displays the absolute value. A higher Lc clears smaller and thinner text.
| Lc (abs) | Clears | Typical use |
|---|---|---|
| 90 | Body text at the smallest and thinnest sizes | Preferred floor for fluent reading |
| 75 | Body text and columns of running copy | Standard body-text target |
| 60 | Larger fluent text and non-body content | Sub-headings, larger paragraphs |
| 45 | Large or bold headline text, large UI shapes | Display type, large buttons |
| 30 | Text that only needs to be noticed | Placeholders, disabled labels, copyright |
| 15 | Non-text elements that carry meaning | Borders, focus rings, icon strokes |
These are readability levels, not strict size cutoffs. The full size-by-weight matrix (pixel size against font weights 100 to 900) lives in the APCA documentation linked under Related concepts.
Color vision deficiency types and prevalence
About 1 in 12 men and 1 in 200 women of Northern-European ancestry have some color vision deficiency. Shadl simulates the three dichromatic types side by side.
| Type | Cone affected | Prevalence (men) | Colors most often confused |
|---|---|---|---|
| Deuteranomaly (green-weak) | M (green), shifted | ~4.6% | green/red, green/brown |
| Deuteranopia (green-blind) | M (green), absent | ~1.2% | green/red, blue/purple |
| Protanomaly (red-weak) | L (red), shifted | ~1.3% | red/green; reds look dim |
| Protanopia (red-blind) | L (red), absent | ~1.0% | red/green/brown; reds darken |
| Tritan (blue-yellow) | S (blue) | ~0.01% (sexes equal) | blue/green, yellow/violet |
| Achromatopsia (monochromacy) | all cones / rods only | ~0.003% | all hues |
Red-green deficiencies (deutan plus protan) account for roughly 99% of cases. That is why a palette leaning on red-versus-green to signal state is the single most common accessibility trap.
OKLCH channels
Shadl draws unlocked swatches from OKLCH and reports each swatch in it. The three channels behave as follows.
| Channel | Range | What it controls | Notes |
|---|---|---|---|
| L (lightness) | 0 to 1 (0% to 100%) | Perceptual brightness; 0 is black, 1 is white | Equal L steps look equally large across hues |
| C (chroma) | 0 to ~0.37 in sRGB | Colorfulness; 0 is neutral gray | Maximum in-gamut chroma depends on L and H |
| H (hue) | 0° to 360° | Hue angle | ~30 red, ~90 yellow, ~145 green, ~195 cyan, ~265 blue, ~330 magenta |
CSS syntax is oklch(L C H), for example oklch(0.52 0.2 27). Not every L/C/H triple is displayable in sRGB; high chroma near black or white clips to the gamut edge.
Export formats for design tokens
Shadl writes the same five swatches (bg, surface, text, primary, accent) into four token formats. Copy whichever matches the target codebase. The snippets below use the default starter palette; the tool emits exact OKLCH conversions for the colors on screen.
| Format | Color model | Drop-in target |
|---|---|---|
| CSS custom properties | hex and oklch | Any stylesheet, inside a :root block |
| Tailwind v4 @theme | oklch | globals.css in a Tailwind v4 project |
| Tailwind v3 config | hex | theme.extend.colors in tailwind.config.js |
| JSON tokens | hex | Design-token pipelines such as Style Dictionary |
:root {
--bg: #f4eedd;
--surface: #e6dbbe;
--text: #1a0e10;
--primary: #c9302a;
--accent: #2a5cff;
}@theme {
--color-bg: oklch(0.94 0.02 90);
--color-surface: oklch(0.88 0.04 88);
--color-text: oklch(0.20 0.02 18);
--color-primary: oklch(0.52 0.20 27);
--color-accent: oklch(0.55 0.24 264);
}module.exports = {
theme: {
extend: {
colors: {
bg: "#f4eedd",
surface: "#e6dbbe",
text: "#1a0e10",
primary: "#c9302a",
accent: "#2a5cff",
},
},
},
};{
"bg": "#f4eedd",
"surface": "#e6dbbe",
"text": "#1a0e10",
"primary": "#c9302a",
"accent": "#2a5cff"
}WCAG contrast: a worked example
The ratio is the brighter relative luminance plus 0.05, divided by the darker plus 0.05. Worked here for gray #767676 text on white #FFFFFF, the lightest gray that still clears AA on white.
| Step | White #FFFFFF | Gray #767676 |
|---|---|---|
| sRGB channel (0 to 1) | 1.000 | 0.463 |
| Linearized channel | 1.000 | 0.181 |
| Relative luminance L | 1.000 | 0.181 |
Linearization applies ((c + 0.055) / 1.055) ^ 2.4 to any channel above 0.03928, then luminance weights the channels 0.2126 R, 0.7152 G, 0.0722 B. The result:
ratio = (1.000 + 0.05) / (0.181 + 0.05)
= 1.05 / 0.231
= 4.54:1That clears the 4.5:1 floor for normal text by a hair, which is exactly why #767676 is the canonical “lightest passing gray” reference value.
Standards and regulations that cite these numbers
Where the thresholds come from and who enforces them.
| Standard | Status / year | Contrast basis | Scope |
|---|---|---|---|
| WCAG 2.0 | W3C Recommendation, 2008 | 4.5:1 (SC 1.4.3) | Foundational web standard |
| WCAG 2.1 | W3C Recommendation, 2018 | adds 3:1 non-text (SC 1.4.11) | Current baseline most audits cite |
| WCAG 2.2 | W3C Recommendation, 2023 | no new contrast SC | Adds focus and target-size criteria |
| WCAG 3.0 | Working Draft, ongoing | APCA (perceptual) | Not normative; do not cite for compliance |
| EN 301 549 | EU harmonized standard | WCAG 2.1 AA | EU public sector and EAA reference |
| EAA, Directive (EU) 2019/882 | Enforced 28 Jun 2025 | WCAG 2.1 AA via EN 301 549 | Private-sector products and services in the EU |
| Section 508 (US) | Revised rule, 2017 | WCAG 2.0 AA | US federal procurement |