OKLCH Studio · Accessible palettes · Industries
Accessible color palette for e-learning for kids (WCAG 2.2 verified)
Updated 2026-10-19
Children's learning products want colour that feels friendly and energetic, and designers often fear that accessibility will force everything into grey. It does not have to. WCAG sets its contrast rules by the text and its background, not by how lively the brand is, and there is plenty of room for high chroma at the lightness values that pass.
There is no separate WCAG standard for children, so the same criteria apply: 4.5:1 for normal text, 3:1 for large text and interface components. Young readers still learning to read benefit from clear letterforms and strong contrast, and children with colour-vision deficiency are often diagnosed late, so colour must never be the only way to tell right from wrong in a quiz.
This palette uses the AA level throughout, with body text solved at AAA anyway because the cost is small on a warm cream page. The status colours are more saturated than in the adult palettes and are still verified as text and as badges with labels.
How to build a palette like this by hand is explained in the accessible colour palette guide; this page is the finished, verified result.
The palette: light and dark
Hex values are the sRGB result after gamut mapping. The oklch() values are those of the final hex, so converting either gives the same colour.
Appointment confirmed
Secondary text sits on the surface colour.
Link in primary · Accent text
Light theme
- Background
#FCF8F0
oklch(0.980 0.011 84.6)
Sample text
- Surface
#FFFEF6
oklch(0.996 0.011 100.8)
Sample text
- Text
#1E1A13
oklch(0.220 0.014 81.6)
Sample text
- Muted text
#5D574D
oklch(0.459 0.018 80.6)
Sample text
- Primary
#0069C2
oklch(0.521 0.161 253.0)
Sample text
- Primary foreground
#FDFCF8
oklch(0.991 0.005 95.1)
Sample text
- Accent
#B53B00
oklch(0.524 0.167 39.2)
Sample text
- Border
#948E83
oklch(0.649 0.018 82.8)
Sample text
- Focus ring
#0059B1
oklch(0.473 0.158 255.4)
Sample text
- Success
#00825B
oklch(0.537 0.115 163.7)
Sample text
- Success fill
#008459
oklch(0.5420 0.1193 161.76)
Sample text
- Success fill label
#FDFCF8
oklch(0.991 0.005 95.1)
Sample text
- Warning
#A56200
oklch(0.5589 0.1252 65.21)
Sample text
- Warning fill
#FFBA00
oklch(0.8309 0.1714 81.55)
Sample text
- Warning fill label
#100F0D
oklch(0.169 0.004 84.6)
Sample text
- Error
#B3001C
oklch(0.483 0.196 24.8)
Sample text
- Error fill
#DB002F
oklch(0.563 0.227 22.5)
Sample text
- Error fill label
#FDFCF8
oklch(0.991 0.005 95.1)
Sample text
- Info
#0077BB
oklch(0.549 0.137 244.6)
Sample text
- Info fill
#0078C4
oklch(0.557 0.147 247.1)
Sample text
- Info fill label
#FDFCF8
oklch(0.991 0.005 95.1)
Sample text
Appointment confirmed
Secondary text sits on the surface colour.
Link in primary · Accent text
Dark theme
- Background
#191610
oklch(0.202 0.012 84.5)
Sample text
- Surface
#23201A
oklch(0.245 0.012 84.6)
Sample text
- Text
#F3EEE4
oklch(0.950 0.014 84.6)
Sample text
- Muted text
#C3BDB1
oklch(0.800 0.018 84.6)
Sample text
- Primary
#00CAFF
oklch(0.781 0.149 225.4)
Sample text
- Primary foreground
#0E0D0B
oklch(0.159 0.004 84.6)
Sample text
- Accent
#FF9D2C
oklch(0.780 0.164 63.5)
Sample text
- Border
#706B60
oklch(0.529 0.018 86.5)
Sample text
- Focus ring
#00CAFF
oklch(0.781 0.149 225.4)
Sample text
- Success
#00EDBE
oklch(0.8425 0.1642 171.51)
Sample text
- Success fill
#00D5A3
oklch(0.775 0.157 168.2)
Sample text
- Success fill label
#100F0D
oklch(0.169 0.004 84.6)
Sample text
- Warning
#FFBC19
oklch(0.835 0.168 81.8)
Sample text
- Warning fill
#EEA000
oklch(0.764 0.162 74.2)
Sample text
- Warning fill label
#100F0D
oklch(0.169 0.004 84.6)
Sample text
- Error
#FF5263
oklch(0.681 0.208 19.2)
Sample text
- Error fill
#FF5A6E
oklch(0.692 0.200 17.0)
Sample text
- Error fill label
#100F0D
oklch(0.169 0.004 84.6)
Sample text
- Info
#1FC6FF
oklch(0.774 0.147 228.6)
Sample text
- Info fill
#00C0FF
oklch(0.758 0.153 231.1)
Sample text
- Info fill label
#100F0D
oklch(0.169 0.004 84.6)
Sample text
Contrast table: every verified pair
Pass or fail uses the raw WCAG 2.x ratio; the ratio shown is floored to two decimals so a near miss is never rounded up. APCA Lc is signed: positive is dark on light, negative is light on dark. Each row opens the pair in the checker.
| Pair | WCAG ratio | Target | Normal AA / AAA | Large AA / AAA | APCA Lc | APCA tier | Check |
|---|---|---|---|---|---|---|---|
| Text on background#1e1a13 on #fcf8f0 | 16.35:1 | AAA 7:1 | Pass / Pass | Pass / Pass | +100.2 | Lc 75: body text | Open in checker |
| Text on surface#1e1a13 on #fffef6 | 17.12:1 | AAA 7:1 | Pass / Pass | Pass / Pass | +103.4 | Lc 75: body text | Open in checker |
| Muted text on background#5d574d on #fcf8f0 | 6.75:1 | AA 4.5:1 | Pass / Fail | Pass / Pass | +80.8 | Lc 75: body text | Open in checker |
| Muted text on surface#5d574d on #fffef6 | 7.07:1 | AA 4.5:1 | Pass / Pass | Pass / Pass | +84.0 | Lc 75: body text | Open in checker |
| Primary as link text on background#0069c2 on #fcf8f0 | 5.21:1 | AA 4.5:1 | Pass / Fail | Pass / Pass | +72.8 | Lc 60: larger content text | Open in checker |
| Primary as link text on surface#0069c2 on #fffef6 | 5.46:1 | AA 4.5:1 | Pass / Fail | Pass / Pass | +76.0 | Lc 75: body text | Open in checker |
| Button label on primary#fdfcf8 on #0069c2 | 5.38:1 | AA 4.5:1 | Pass / Fail | Pass / Pass | −80.1 | Lc 75: body text | Open in checker |
| Accent text on background#b53b00 on #fcf8f0 | 5.52:1 | AA 4.5:1 | Pass / Fail | Pass / Pass | +74.1 | Lc 60: larger content text | Open in checker |
| Accent text on surface#b53b00 on #fffef6 | 5.78:1 | AA 4.5:1 | Pass / Fail | Pass / Pass | +77.3 | Lc 75: body text | Open in checker |
| Border on background#948e83 on #fcf8f0 | 3.07:1 | 3:1 (WCAG 1.4.11) | Fail / Fail | Pass / Fail | +55.8 | Lc 45: headlines and large text | Open in checker |
| Border on surface#948e83 on #fffef6 | 3.21:1 | 3:1 (WCAG 1.4.11) | Fail / Fail | Pass / Fail | +59.0 | Lc 45: headlines and large text | Open in checker |
| Focus ring on background#0059b1 on #fcf8f0 | 6.47:1 | 3:1 (WCAG 1.4.11) | Pass / Fail | Pass / Pass | +78.9 | Lc 75: body text | Open in checker |
| Focus ring on surface#0059b1 on #fffef6 | 6.77:1 | 3:1 (WCAG 1.4.11) | Pass / Fail | Pass / Pass | +82.1 | Lc 75: body text | Open in checker |
| Success text on background#00825b on #fcf8f0 | 4.56:1 | AA 4.5:1 | Pass / Fail | Pass / Pass | +68.9 | Lc 60: larger content text | Open in checker |
| Success text on surface#00825b on #fffef6 | 4.77:1 | AA 4.5:1 | Pass / Fail | Pass / Pass | +72.1 | Lc 60: larger content text | Open in checker |
| Success badge label on fill#fdfcf8 on #008459 | 4.60:1 | AA 4.5:1 | Pass / Fail | Pass / Pass | −75.6 | Lc 75: body text | Open in checker |
| Warning text on background#a56200 on #fcf8f0 | 4.56:1 | AA 4.5:1 | Pass / Fail | Pass / Pass | +69.1 | Lc 60: larger content text | Open in checker |
| Warning text on surface#a56200 on #fffef6 | 4.77:1 | AA 4.5:1 | Pass / Fail | Pass / Pass | +72.3 | Lc 60: larger content text | Open in checker |
| Warning badge label on fill#100f0d on #ffba00 | 11.19:1 | AA 4.5:1 | Pass / Pass | Pass / Pass | +72.9 | Lc 60: larger content text | Open in checker |
| Error text on background#b3001c on #fcf8f0 | 6.75:1 | AA 4.5:1 | Pass / Fail | Pass / Pass | +78.2 | Lc 75: body text | Open in checker |
| Error text on surface#b3001c on #fffef6 | 7.07:1 | AA 4.5:1 | Pass / Pass | Pass / Pass | +81.4 | Lc 75: body text | Open in checker |
| Error badge label on fill#fdfcf8 on #db002f | 5.04:1 | AA 4.5:1 | Pass / Fail | Pass / Pass | −76.2 | Lc 75: body text | Open in checker |
| Info text on background#0077bb on #fcf8f0 | 4.55:1 | AA 4.5:1 | Pass / Fail | Pass / Pass | +68.8 | Lc 60: larger content text | Open in checker |
| Info text on surface#0077bb on #fffef6 | 4.76:1 | AA 4.5:1 | Pass / Fail | Pass / Pass | +72.0 | Lc 60: larger content text | Open in checker |
| Info badge label on fill#fdfcf8 on #0078c4 | 4.56:1 | AA 4.5:1 | Pass / Fail | Pass / Pass | −75.3 | Lc 75: body text | Open in checker |
| Pair | WCAG ratio | Target | Normal AA / AAA | Large AA / AAA | APCA Lc | APCA tier | Check |
|---|---|---|---|---|---|---|---|
| Text on background#f3eee4 on #191610 | 15.60:1 | AAA 7:1 | Pass / Pass | Pass / Pass | −96.1 | Lc 75: body text | Open in checker |
| Text on surface#f3eee4 on #23201a | 14.04:1 | AAA 7:1 | Pass / Pass | Pass / Pass | −94.8 | Lc 75: body text | Open in checker |
| Muted text on background#c3bdb1 on #191610 | 9.65:1 | AA 4.5:1 | Pass / Pass | Pass / Pass | −66.2 | Lc 60: larger content text | Open in checker |
| Muted text on surface#c3bdb1 on #23201a | 8.68:1 | AA 4.5:1 | Pass / Pass | Pass / Pass | −65.0 | Lc 60: larger content text | Open in checker |
| Primary as link text on background#00caff on #191610 | 9.36:1 | AA 4.5:1 | Pass / Pass | Pass / Pass | −65.4 | Lc 60: larger content text | Open in checker |
| Primary as link text on surface#00caff on #23201a | 8.42:1 | AA 4.5:1 | Pass / Pass | Pass / Pass | −64.1 | Lc 60: larger content text | Open in checker |
| Button label on primary#0e0d0b on #00caff | 10.07:1 | AA 4.5:1 | Pass / Pass | Pass / Pass | +67.3 | Lc 60: larger content text | Open in checker |
| Accent text on background#ff9d2c on #191610 | 8.69:1 | AA 4.5:1 | Pass / Pass | Pass / Pass | −61.2 | Lc 60: larger content text | Open in checker |
| Accent text on surface#ff9d2c on #23201a | 7.82:1 | AA 4.5:1 | Pass / Pass | Pass / Pass | −60.0 | Lc 45: headlines and large text | Open in checker |
| Border on background#706b60 on #191610 | 3.40:1 | 3:1 (WCAG 1.4.11) | Fail / Fail | Pass / Fail | −24.4 | Below Lc 30 | Open in checker |
| Border on surface#706b60 on #23201a | 3.06:1 | 3:1 (WCAG 1.4.11) | Fail / Fail | Pass / Fail | −23.2 | Below Lc 30 | Open in checker |
| Focus ring on background#00caff on #191610 | 9.36:1 | 3:1 (WCAG 1.4.11) | Pass / Pass | Pass / Pass | −65.4 | Lc 60: larger content text | Open in checker |
| Focus ring on surface#00caff on #23201a | 8.42:1 | 3:1 (WCAG 1.4.11) | Pass / Pass | Pass / Pass | −64.1 | Lc 60: larger content text | Open in checker |
| Success text on background#00edbe on #191610 | 11.90:1 | AA 4.5:1 | Pass / Pass | Pass / Pass | −79.0 | Lc 75: body text | Open in checker |
| Success text on surface#00edbe on #23201a | 10.71:1 | AA 4.5:1 | Pass / Pass | Pass / Pass | −77.8 | Lc 75: body text | Open in checker |
| Success badge label on fill#100f0d on #00d5a3 | 10.07:1 | AA 4.5:1 | Pass / Pass | Pass / Pass | +67.9 | Lc 60: larger content text | Open in checker |
| Warning text on background#ffbc19 on #191610 | 10.70:1 | AA 4.5:1 | Pass / Pass | Pass / Pass | −72.2 | Lc 60: larger content text | Open in checker |
| Warning text on surface#ffbc19 on #23201a | 9.63:1 | AA 4.5:1 | Pass / Pass | Pass / Pass | −71.0 | Lc 60: larger content text | Open in checker |
| Warning badge label on fill#100f0d on #eea000 | 8.81:1 | AA 4.5:1 | Pass / Pass | Pass / Pass | +61.1 | Lc 60: larger content text | Open in checker |
| Error text on background#ff5263 on #191610 | 5.70:1 | AA 4.5:1 | Pass / Fail | Pass / Pass | −43.2 | Lc 30: non-text and incidental | Open in checker |
| Error text on surface#ff5263 on #23201a | 5.13:1 | AA 4.5:1 | Pass / Fail | Pass / Pass | −42.0 | Lc 30: non-text and incidental | Open in checker |
| Error badge label on fill#100f0d on #ff5a6e | 6.33:1 | AA 4.5:1 | Pass / Fail | Pass / Pass | +47.5 | Lc 45: headlines and large text | Open in checker |
| Info text on background#1fc6ff on #191610 | 9.09:1 | AA 4.5:1 | Pass / Pass | Pass / Pass | −63.7 | Lc 60: larger content text | Open in checker |
| Info text on surface#1fc6ff on #23201a | 8.18:1 | AA 4.5:1 | Pass / Pass | Pass / Pass | −62.5 | Lc 60: larger content text | Open in checker |
| Info badge label on fill#100f0d on #00c0ff | 9.10:1 | AA 4.5:1 | Pass / Pass | Pass / Pass | +63.0 | Lc 60: larger content text | Open in checker |
Status colours and colour blindness
The four status fills were simulated for protanopia, deuteranopia and tritanopia (Machado et al., 2009). Success against error, the pair most often confused, must stay at least 6 ΔE-OK ×100 apart under every simulation. The other pairs are shown for information, so keep an icon and a word on every status.
| Pair | Normal vision | Protanopia | Deuteranopia | Tritanopia | Held to 6 |
|---|---|---|---|---|---|
| success / warning | 34.7 | 26.9 | 41.0 | 31.3 | Shown only |
| success / error | 32.7 | 31.9 | 11.2 | 35.6 | Yes |
| success / info | 18.2 | 17.7 | 17.2 | 3.8 | Shown only |
| warning / error | 33.6 | 58.5 | 49.9 | 20.3 | Shown only |
| warning / info | 41.8 | 36.8 | 48.6 | 30.1 | Shown only |
| error / info | 34.7 | 34.7 | 24.2 | 35.8 | Shown only |
Fills as simulated:Normal visionProtanopiaDeuteranopiaTritanopia
| Pair | Normal vision | Protanopia | Deuteranopia | Tritanopia | Held to 6 |
|---|---|---|---|---|---|
| success / warning | 23.3 | 13.3 | 20.7 | 29.8 | Shown only |
| success / error | 35.5 | 24.3 | 8.3 | 37.4 | Yes |
| success / info | 16.2 | 15.1 | 14.8 | 2.9 | Shown only |
| warning / error | 19.0 | 22.5 | 18.5 | 9.1 | Shown only |
| warning / info | 30.8 | 26.9 | 34.6 | 29.4 | Shown only |
| error / info | 34.4 | 25.6 | 22.1 | 36.6 | Shown only |
Fills as simulated:Normal visionProtanopiaDeuteranopiaTritanopia
Why these colours
The primary is a vivid blue at OKLCH hue 240 with chroma 0.19, well above the restrained values used in other palettes. At the lightness needed for white button labels it is a rich royal blue rather than a pale sky. The accent is an energetic orange at hue 55, the complement of blue, which makes buttons and rewards stand out strongly.
The page background is a warm cream instead of white. It lowers glare and makes the saturated colours feel part of a toy box rather than a medical form. For the quiz states, success is a bluish green and error a red-orange, separated in lightness so a wrong answer is not confused with a right one in the common colour-vision deficiencies.
The generator solved 50 pairs (25 light, 25 dark), and all of them meet their target on the raw WCAG ratio. The tightest is info text on background in the light theme at 4.55:1 against a target of 4.5:1. After gamut mapping to sRGB the light primary keeps 85% of the requested chroma; hue was held throughout.
How to use it
- Mark right and wrong answers with shapes and words, such as a tick and Correct, in addition to green and red.
- Keep large touch targets and use the border colour to outline answer buttons so their edges are visible against the page.
- Use the accent orange for rewards and the primary button, but keep paragraphs of instruction in the strong text colour.
- Avoid animated colour changes as the only feedback, and respect reduced-motion settings.
- Keep text on illustrated backgrounds inside a solid panel, since busy art removes the contrast guarantee.
Export
Generated from the verified values above, never typed by hand. Light and dark are both included.
CSS custom properties (hex, then oklch())
/* sRGB hex first: every browser. */
:root {
--color-background: #fcf8f0;
--color-surface: #fffef6;
--color-text: #1e1a13;
--color-text-muted: #5d574d;
--color-primary: #0069c2;
--color-primary-foreground: #fdfcf8;
--color-accent: #b53b00;
--color-border: #948e83;
--color-focus-ring: #0059b1;
--color-success: #00825b;
--color-success-solid: #008459;
--color-success-solid-foreground: #fdfcf8;
--color-warning: #a56200;
--color-warning-solid: #ffba00;
--color-warning-solid-foreground: #100f0d;
--color-error: #b3001c;
--color-error-solid: #db002f;
--color-error-solid-foreground: #fdfcf8;
--color-info: #0077bb;
--color-info-solid: #0078c4;
--color-info-solid-foreground: #fdfcf8;
}
.dark {
--color-background: #191610;
--color-surface: #23201a;
--color-text: #f3eee4;
--color-text-muted: #c3bdb1;
--color-primary: #00caff;
--color-primary-foreground: #0e0d0b;
--color-accent: #ff9d2c;
--color-border: #706b60;
--color-focus-ring: #00caff;
--color-success: #00edbe;
--color-success-solid: #00d5a3;
--color-success-solid-foreground: #100f0d;
--color-warning: #ffbc19;
--color-warning-solid: #eea000;
--color-warning-solid-foreground: #100f0d;
--color-error: #ff5263;
--color-error-solid: #ff5a6e;
--color-error-solid-foreground: #100f0d;
--color-info: #1fc6ff;
--color-info-solid: #00c0ff;
--color-info-solid-foreground: #100f0d;
}
/* oklch() where supported: the same colours, unclipped values of the hex above. */
@supports (color: oklch(0 0 0)) {
:root {
--color-background: oklch(0.980 0.011 84.6);
--color-surface: oklch(0.996 0.011 100.8);
--color-text: oklch(0.220 0.014 81.6);
--color-text-muted: oklch(0.459 0.018 80.6);
--color-primary: oklch(0.521 0.161 253.0);
--color-primary-foreground: oklch(0.991 0.005 95.1);
--color-accent: oklch(0.524 0.167 39.2);
--color-border: oklch(0.649 0.018 82.8);
--color-focus-ring: oklch(0.473 0.158 255.4);
--color-success: oklch(0.537 0.115 163.7);
--color-success-solid: oklch(0.5420 0.1193 161.76);
--color-success-solid-foreground: oklch(0.991 0.005 95.1);
--color-warning: oklch(0.5589 0.1252 65.21);
--color-warning-solid: oklch(0.8309 0.1714 81.55);
--color-warning-solid-foreground: oklch(0.169 0.004 84.6);
--color-error: oklch(0.483 0.196 24.8);
--color-error-solid: oklch(0.563 0.227 22.5);
--color-error-solid-foreground: oklch(0.991 0.005 95.1);
--color-info: oklch(0.549 0.137 244.6);
--color-info-solid: oklch(0.557 0.147 247.1);
--color-info-solid-foreground: oklch(0.991 0.005 95.1);
}
.dark {
--color-background: oklch(0.202 0.012 84.5);
--color-surface: oklch(0.245 0.012 84.6);
--color-text: oklch(0.950 0.014 84.6);
--color-text-muted: oklch(0.800 0.018 84.6);
--color-primary: oklch(0.781 0.149 225.4);
--color-primary-foreground: oklch(0.159 0.004 84.6);
--color-accent: oklch(0.780 0.164 63.5);
--color-border: oklch(0.529 0.018 86.5);
--color-focus-ring: oklch(0.781 0.149 225.4);
--color-success: oklch(0.8425 0.1642 171.51);
--color-success-solid: oklch(0.775 0.157 168.2);
--color-success-solid-foreground: oklch(0.169 0.004 84.6);
--color-warning: oklch(0.835 0.168 81.8);
--color-warning-solid: oklch(0.764 0.162 74.2);
--color-warning-solid-foreground: oklch(0.169 0.004 84.6);
--color-error: oklch(0.681 0.208 19.2);
--color-error-solid: oklch(0.692 0.200 17.0);
--color-error-solid-foreground: oklch(0.169 0.004 84.6);
--color-info: oklch(0.774 0.147 228.6);
--color-info-solid: oklch(0.758 0.153 231.1);
--color-info-solid-foreground: oklch(0.169 0.004 84.6);
}
}Tailwind CSS v4 @theme
@theme {
/* light */
--color-background: oklch(0.980 0.011 84.6); /* #fcf8f0 */
--color-surface: oklch(0.996 0.011 100.8); /* #fffef6 */
--color-text: oklch(0.220 0.014 81.6); /* #1e1a13 */
--color-text-muted: oklch(0.459 0.018 80.6); /* #5d574d */
--color-primary: oklch(0.521 0.161 253.0); /* #0069c2 */
--color-primary-foreground: oklch(0.991 0.005 95.1); /* #fdfcf8 */
--color-accent: oklch(0.524 0.167 39.2); /* #b53b00 */
--color-border: oklch(0.649 0.018 82.8); /* #948e83 */
--color-focus-ring: oklch(0.473 0.158 255.4); /* #0059b1 */
--color-success: oklch(0.537 0.115 163.7); /* #00825b */
--color-success-solid: oklch(0.5420 0.1193 161.76); /* #008459 */
--color-success-solid-foreground: oklch(0.991 0.005 95.1); /* #fdfcf8 */
--color-warning: oklch(0.5589 0.1252 65.21); /* #a56200 */
--color-warning-solid: oklch(0.8309 0.1714 81.55); /* #ffba00 */
--color-warning-solid-foreground: oklch(0.169 0.004 84.6); /* #100f0d */
--color-error: oklch(0.483 0.196 24.8); /* #b3001c */
--color-error-solid: oklch(0.563 0.227 22.5); /* #db002f */
--color-error-solid-foreground: oklch(0.991 0.005 95.1); /* #fdfcf8 */
--color-info: oklch(0.549 0.137 244.6); /* #0077bb */
--color-info-solid: oklch(0.557 0.147 247.1); /* #0078c4 */
--color-info-solid-foreground: oklch(0.991 0.005 95.1); /* #fdfcf8 */
/* dark: use as dark:bg-background-dark, or remap under a .dark selector */
--color-background-dark: oklch(0.202 0.012 84.5); /* #191610 */
--color-surface-dark: oklch(0.245 0.012 84.6); /* #23201a */
--color-text-dark: oklch(0.950 0.014 84.6); /* #f3eee4 */
--color-text-muted-dark: oklch(0.800 0.018 84.6); /* #c3bdb1 */
--color-primary-dark: oklch(0.781 0.149 225.4); /* #00caff */
--color-primary-foreground-dark: oklch(0.159 0.004 84.6); /* #0e0d0b */
--color-accent-dark: oklch(0.780 0.164 63.5); /* #ff9d2c */
--color-border-dark: oklch(0.529 0.018 86.5); /* #706b60 */
--color-focus-ring-dark: oklch(0.781 0.149 225.4); /* #00caff */
--color-success-dark: oklch(0.8425 0.1642 171.51); /* #00edbe */
--color-success-solid-dark: oklch(0.775 0.157 168.2); /* #00d5a3 */
--color-success-solid-foreground-dark: oklch(0.169 0.004 84.6); /* #100f0d */
--color-warning-dark: oklch(0.835 0.168 81.8); /* #ffbc19 */
--color-warning-solid-dark: oklch(0.764 0.162 74.2); /* #eea000 */
--color-warning-solid-foreground-dark: oklch(0.169 0.004 84.6); /* #100f0d */
--color-error-dark: oklch(0.681 0.208 19.2); /* #ff5263 */
--color-error-solid-dark: oklch(0.692 0.200 17.0); /* #ff5a6e */
--color-error-solid-foreground-dark: oklch(0.169 0.004 84.6); /* #100f0d */
--color-info-dark: oklch(0.774 0.147 228.6); /* #1fc6ff */
--color-info-solid-dark: oklch(0.758 0.153 231.1); /* #00c0ff */
--color-info-solid-foreground-dark: oklch(0.169 0.004 84.6); /* #100f0d */
}shadcn/ui variables (:root and .dark)
:root {
--background: oklch(0.980 0.011 84.6);
--foreground: oklch(0.220 0.014 81.6);
--card: oklch(0.996 0.011 100.8);
--card-foreground: oklch(0.220 0.014 81.6);
--popover: oklch(0.996 0.011 100.8);
--popover-foreground: oklch(0.220 0.014 81.6);
--primary: oklch(0.521 0.161 253.0);
--primary-foreground: oklch(0.991 0.005 95.1);
--secondary: oklch(0.996 0.011 100.8);
--secondary-foreground: oklch(0.220 0.014 81.6);
--muted: oklch(0.996 0.011 100.8);
--muted-foreground: oklch(0.459 0.018 80.6);
--accent: oklch(0.996 0.011 100.8);
--accent-foreground: oklch(0.220 0.014 81.6);
--destructive: oklch(0.563 0.227 22.5);
--destructive-foreground: oklch(0.991 0.005 95.1);
--border: oklch(0.649 0.018 82.8);
--input: oklch(0.649 0.018 82.8);
--ring: oklch(0.473 0.158 255.4);
--success: oklch(0.5420 0.1193 161.76);
--success-foreground: oklch(0.991 0.005 95.1);
--warning: oklch(0.8309 0.1714 81.55);
--warning-foreground: oklch(0.169 0.004 84.6);
--info: oklch(0.557 0.147 247.1);
--info-foreground: oklch(0.991 0.005 95.1);
--brand-accent: oklch(0.524 0.167 39.2);
}
.dark {
--background: oklch(0.202 0.012 84.5);
--foreground: oklch(0.950 0.014 84.6);
--card: oklch(0.245 0.012 84.6);
--card-foreground: oklch(0.950 0.014 84.6);
--popover: oklch(0.245 0.012 84.6);
--popover-foreground: oklch(0.950 0.014 84.6);
--primary: oklch(0.781 0.149 225.4);
--primary-foreground: oklch(0.159 0.004 84.6);
--secondary: oklch(0.245 0.012 84.6);
--secondary-foreground: oklch(0.950 0.014 84.6);
--muted: oklch(0.245 0.012 84.6);
--muted-foreground: oklch(0.800 0.018 84.6);
--accent: oklch(0.245 0.012 84.6);
--accent-foreground: oklch(0.950 0.014 84.6);
--destructive: oklch(0.692 0.200 17.0);
--destructive-foreground: oklch(0.169 0.004 84.6);
--border: oklch(0.529 0.018 86.5);
--input: oklch(0.529 0.018 86.5);
--ring: oklch(0.781 0.149 225.4);
--success: oklch(0.775 0.157 168.2);
--success-foreground: oklch(0.169 0.004 84.6);
--warning: oklch(0.764 0.162 74.2);
--warning-foreground: oklch(0.169 0.004 84.6);
--info: oklch(0.758 0.153 231.1);
--info-foreground: oklch(0.169 0.004 84.6);
--brand-accent: oklch(0.780 0.164 63.5);
}Design tokens (DTCG-style JSON)
{
"color": {
"light": {
"background": {
"$type": "color",
"$value": "oklch(0.980 0.011 84.6)",
"$description": "sRGB #fcf8f0"
},
"surface": {
"$type": "color",
"$value": "oklch(0.996 0.011 100.8)",
"$description": "sRGB #fffef6"
},
"text": {
"$type": "color",
"$value": "oklch(0.220 0.014 81.6)",
"$description": "sRGB #1e1a13"
},
"text-muted": {
"$type": "color",
"$value": "oklch(0.459 0.018 80.6)",
"$description": "sRGB #5d574d"
},
"primary": {
"$type": "color",
"$value": "oklch(0.521 0.161 253.0)",
"$description": "sRGB #0069c2"
},
"primary-foreground": {
"$type": "color",
"$value": "oklch(0.991 0.005 95.1)",
"$description": "sRGB #fdfcf8"
},
"accent": {
"$type": "color",
"$value": "oklch(0.524 0.167 39.2)",
"$description": "sRGB #b53b00"
},
"border": {
"$type": "color",
"$value": "oklch(0.649 0.018 82.8)",
"$description": "sRGB #948e83"
},
"focus-ring": {
"$type": "color",
"$value": "oklch(0.473 0.158 255.4)",
"$description": "sRGB #0059b1"
},
"success": {
"$type": "color",
"$value": "oklch(0.537 0.115 163.7)",
"$description": "sRGB #00825b"
},
"success-solid": {
"$type": "color",
"$value": "oklch(0.5420 0.1193 161.76)",
"$description": "sRGB #008459"
},
"success-solid-foreground": {
"$type": "color",
"$value": "oklch(0.991 0.005 95.1)",
"$description": "sRGB #fdfcf8"
},
"warning": {
"$type": "color",
"$value": "oklch(0.5589 0.1252 65.21)",
"$description": "sRGB #a56200"
},
"warning-solid": {
"$type": "color",
"$value": "oklch(0.8309 0.1714 81.55)",
"$description": "sRGB #ffba00"
},
"warning-solid-foreground": {
"$type": "color",
"$value": "oklch(0.169 0.004 84.6)",
"$description": "sRGB #100f0d"
},
"error": {
"$type": "color",
"$value": "oklch(0.483 0.196 24.8)",
"$description": "sRGB #b3001c"
},
"error-solid": {
"$type": "color",
"$value": "oklch(0.563 0.227 22.5)",
"$description": "sRGB #db002f"
},
"error-solid-foreground": {
"$type": "color",
"$value": "oklch(0.991 0.005 95.1)",
"$description": "sRGB #fdfcf8"
},
"info": {
"$type": "color",
"$value": "oklch(0.549 0.137 244.6)",
"$description": "sRGB #0077bb"
},
"info-solid": {
"$type": "color",
"$value": "oklch(0.557 0.147 247.1)",
"$description": "sRGB #0078c4"
},
"info-solid-foreground": {
"$type": "color",
"$value": "oklch(0.991 0.005 95.1)",
"$description": "sRGB #fdfcf8"
}
},
"dark": {
"background": {
"$type": "color",
"$value": "oklch(0.202 0.012 84.5)",
"$description": "sRGB #191610"
},
"surface": {
"$type": "color",
"$value": "oklch(0.245 0.012 84.6)",
"$description": "sRGB #23201a"
},
"text": {
"$type": "color",
"$value": "oklch(0.950 0.014 84.6)",
"$description": "sRGB #f3eee4"
},
"text-muted": {
"$type": "color",
"$value": "oklch(0.800 0.018 84.6)",
"$description": "sRGB #c3bdb1"
},
"primary": {
"$type": "color",
"$value": "oklch(0.781 0.149 225.4)",
"$description": "sRGB #00caff"
},
"primary-foreground": {
"$type": "color",
"$value": "oklch(0.159 0.004 84.6)",
"$description": "sRGB #0e0d0b"
},
"accent": {
"$type": "color",
"$value": "oklch(0.780 0.164 63.5)",
"$description": "sRGB #ff9d2c"
},
"border": {
"$type": "color",
"$value": "oklch(0.529 0.018 86.5)",
"$description": "sRGB #706b60"
},
"focus-ring": {
"$type": "color",
"$value": "oklch(0.781 0.149 225.4)",
"$description": "sRGB #00caff"
},
"success": {
"$type": "color",
"$value": "oklch(0.8425 0.1642 171.51)",
"$description": "sRGB #00edbe"
},
"success-solid": {
"$type": "color",
"$value": "oklch(0.775 0.157 168.2)",
"$description": "sRGB #00d5a3"
},
"success-solid-foreground": {
"$type": "color",
"$value": "oklch(0.169 0.004 84.6)",
"$description": "sRGB #100f0d"
},
"warning": {
"$type": "color",
"$value": "oklch(0.835 0.168 81.8)",
"$description": "sRGB #ffbc19"
},
"warning-solid": {
"$type": "color",
"$value": "oklch(0.764 0.162 74.2)",
"$description": "sRGB #eea000"
},
"warning-solid-foreground": {
"$type": "color",
"$value": "oklch(0.169 0.004 84.6)",
"$description": "sRGB #100f0d"
},
"error": {
"$type": "color",
"$value": "oklch(0.681 0.208 19.2)",
"$description": "sRGB #ff5263"
},
"error-solid": {
"$type": "color",
"$value": "oklch(0.692 0.200 17.0)",
"$description": "sRGB #ff5a6e"
},
"error-solid-foreground": {
"$type": "color",
"$value": "oklch(0.169 0.004 84.6)",
"$description": "sRGB #100f0d"
},
"info": {
"$type": "color",
"$value": "oklch(0.774 0.147 228.6)",
"$description": "sRGB #1fc6ff"
},
"info-solid": {
"$type": "color",
"$value": "oklch(0.758 0.153 231.1)",
"$description": "sRGB #00c0ff"
},
"info-solid-foreground": {
"$type": "color",
"$value": "oklch(0.169 0.004 84.6)",
"$description": "sRGB #100f0d"
}
}
}
}Open in the studio
Take the primary colour into the picker, build a tonal scale from it, or check any pair of your own.
Open #0069C2 in the OKLCH picker →Build a tonal scale →Check a pair
FAQ
- Can bright colours really be accessible?
- Yes. Contrast depends on lightness difference, not saturation. The solver holds chroma and hue and only adjusts lightness, so the colours stay lively, and the table shows each pair's measured ratio.
- Which age group is this for?
- It suits early readers through primary school. It makes no medical or developmental claims; it applies the standard WCAG contrast criteria with extra headroom for text.
- Why a cream background?
- Pure white next to saturated colour can feel harsh, especially on bright screens. A light warm tone keeps contrast high while feeling softer. The value is verified like every other pair.
- What about children with colour blindness?
- The success and error fills are checked under simulated protanopia, deuteranopia and tritanopia. You should still add icons or text, as WCAG 1.4.1 asks.