OKLCH Studio · Accessible palettes · Industries
Accessible color palette for e-commerce (WCAG 2.2 verified)
Updated 2026-10-19
Online shops live and die by a small set of screens: product grids, product pages, basket and checkout. Colour does a lot of work there. It signals the buy button, marks a sale, shows whether something is in stock and flags a problem with a card number. When any of those roles lacks contrast or relies on colour alone, shoppers leave and some cannot buy at all.
Retail is also where accessibility complaints are common, and consumer-facing rules in some regions, for example the European Accessibility Act for certain e-commerce services, point toward WCAG-based standards. WCAG 2.2 AA is the usual baseline. This palette meets it for every listed pair and is not legal advice.
Prices deserve special care. A struck-through old price in light grey next to a sale price is a common failure; the muted text colour here is verified so the old price remains readable as well as visually secondary.
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
#F7F7F7
oklch(0.976 0.000 0.0)
Sample text
- Surface
#FEFEFE
oklch(0.997 0.000 0.0)
Sample text
- Text
#1B1B1B
oklch(0.222 0.000 0.0)
Sample text
- Muted text
#585858
oklch(0.460 0.000 0.0)
Sample text
- Primary
#4B53C2
oklch(0.500 0.171 275.2)
Sample text
- Primary foreground
#FCFCFC
oklch(0.991 0.000 0.0)
Sample text
- Accent
#B33C00
oklch(0.5217 0.1643 39.84)
Sample text
- Border
#8E8E8E
oklch(0.647 0.000 0.0)
Sample text
- Focus ring
#3E44B1
oklch(0.450 0.170 274.8)
Sample text
- Success
#008158
oklch(0.5333 0.1163 162.37)
Sample text
- Success fill
#008558
oklch(0.545 0.122 160.9)
Sample text
- Success fill label
#FCFCFC
oklch(0.991 0.000 0.0)
Sample text
- Warning
#A16300
oklch(0.555 0.122 67.9)
Sample text
- Warning fill
#FFBA44
oklch(0.8335 0.1508 76.88)
Sample text
- Warning fill label
#0F0F0F
oklch(0.168 0.000 0.0)
Sample text
- Error
#A21A1B
oklch(0.4603 0.1706 26.95)
Sample text
- Error fill
#C8322E
oklch(0.551 0.187 27.1)
Sample text
- Error fill label
#FCFCFC
oklch(0.991 0.000 0.0)
Sample text
- Info
#2274AF
oklch(0.540 0.120 245.0)
Sample text
- Info fill
#1377B9
oklch(0.5501 0.1324 245.13)
Sample text
- Info fill label
#FCFCFC
oklch(0.991 0.000 0.0)
Sample text
Appointment confirmed
Secondary text sits on the surface colour.
Link in primary · Accent text
Dark theme
- Background
#161616
oklch(0.200 0.000 0.0)
Sample text
- Surface
#202020
oklch(0.244 0.000 0.0)
Sample text
- Text
#EEEEEE
oklch(0.949 0.000 0.0)
Sample text
- Muted text
#BEBEBE
oklch(0.802 0.000 0.0)
Sample text
- Primary
#9FB2FF
oklch(0.779 0.112 272.9)
Sample text
- Primary foreground
#0D0D0D
oklch(0.159 0.000 0.0)
Sample text
- Accent
#FF9C5F
oklch(0.783 0.141 51.1)
Sample text
- Border
#6B6B6B
oklch(0.528 0.000 0.0)
Sample text
- Focus ring
#9FB2FF
oklch(0.779 0.112 272.9)
Sample text
- Success
#6CE5B5
oklch(0.839 0.130 164.9)
Sample text
- Success fill
#3BCD9A
oklch(0.759 0.143 165.0)
Sample text
- Success fill label
#0F0F0F
oklch(0.168 0.000 0.0)
Sample text
- Warning
#FFBC56
oklch(0.839 0.140 75.1)
Sample text
- Warning fill
#E9A11D
oklch(0.7605 0.1539 75.30)
Sample text
- Warning fill label
#0F0F0F
oklch(0.168 0.000 0.0)
Sample text
- Error
#F66D62
oklch(0.700 0.171 27.0)
Sample text
- Error fill
#FF7A6D
oklch(0.732 0.165 27.5)
Sample text
- Error fill label
#0F0F0F
oklch(0.168 0.000 0.0)
Sample text
- Info
#71BFFF
oklch(0.780 0.120 245.0)
Sample text
- Info fill
#61B9FF
oklch(0.760 0.132 244.8)
Sample text
- Info fill label
#0F0F0F
oklch(0.168 0.000 0.0)
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#1b1b1b on #f7f7f7 | 16.07:1 | AAA 7:1 | Pass / Pass | Pass / Pass | +99.3 | Lc 75: body text | Open in checker |
| Text on surface#1b1b1b on #fefefe | 17.07:1 | AAA 7:1 | Pass / Pass | Pass / Pass | +103.5 | Lc 75: body text | Open in checker |
| Muted text on background#585858 on #f7f7f7 | 6.64:1 | AA 4.5:1 | Pass / Fail | Pass / Pass | +79.9 | Lc 75: body text | Open in checker |
| Muted text on surface#585858 on #fefefe | 7.05:1 | AA 4.5:1 | Pass / Pass | Pass / Pass | +84.1 | Lc 75: body text | Open in checker |
| Primary as link text on background#4b53c2 on #f7f7f7 | 5.91:1 | AA 4.5:1 | Pass / Fail | Pass / Pass | +76.3 | Lc 75: body text | Open in checker |
| Primary as link text on surface#4b53c2 on #fefefe | 6.28:1 | AA 4.5:1 | Pass / Fail | Pass / Pass | +80.5 | Lc 75: body text | Open in checker |
| Button label on primary#fcfcfc on #4b53c2 | 6.17:1 | AA 4.5:1 | Pass / Fail | Pass / Pass | −84.3 | Lc 75: body text | Open in checker |
| Accent text on background#b33c00 on #f7f7f7 | 5.50:1 | AA 4.5:1 | Pass / Fail | Pass / Pass | +73.6 | Lc 60: larger content text | Open in checker |
| Accent text on surface#b33c00 on #fefefe | 5.84:1 | AA 4.5:1 | Pass / Fail | Pass / Pass | +77.8 | Lc 75: body text | Open in checker |
| Border on background#8e8e8e on #f7f7f7 | 3.05:1 | 3:1 (WCAG 1.4.11) | Fail / Fail | Pass / Fail | +55.3 | Lc 45: headlines and large text | Open in checker |
| Border on surface#8e8e8e on #fefefe | 3.24:1 | 3:1 (WCAG 1.4.11) | Fail / Fail | Pass / Fail | +59.5 | Lc 45: headlines and large text | Open in checker |
| Focus ring on background#3e44b1 on #f7f7f7 | 7.35:1 | 3:1 (WCAG 1.4.11) | Pass / Pass | Pass / Pass | +82.1 | Lc 75: body text | Open in checker |
| Focus ring on surface#3e44b1 on #fefefe | 7.80:1 | 3:1 (WCAG 1.4.11) | Pass / Pass | Pass / Pass | +86.2 | Lc 75: body text | Open in checker |
| Success text on background#008158 on #f7f7f7 | 4.57:1 | AA 4.5:1 | Pass / Fail | Pass / Pass | +68.6 | Lc 60: larger content text | Open in checker |
| Success text on surface#008158 on #fefefe | 4.86:1 | AA 4.5:1 | Pass / Fail | Pass / Pass | +72.8 | Lc 60: larger content text | Open in checker |
| Success badge label on fill#fcfcfc on #008558 | 4.55:1 | AA 4.5:1 | Pass / Fail | Pass / Pass | −75.3 | Lc 75: body text | Open in checker |
| Warning text on background#a16300 on #f7f7f7 | 4.55:1 | AA 4.5:1 | Pass / Fail | Pass / Pass | +68.7 | Lc 60: larger content text | Open in checker |
| Warning text on surface#a16300 on #fefefe | 4.84:1 | AA 4.5:1 | Pass / Fail | Pass / Pass | +72.9 | Lc 60: larger content text | Open in checker |
| Warning badge label on fill#0f0f0f on #ffba44 | 11.28:1 | AA 4.5:1 | Pass / Pass | Pass / Pass | +73.2 | Lc 60: larger content text | Open in checker |
| Error text on background#a21a1b on #f7f7f7 | 7.25:1 | AA 4.5:1 | Pass / Pass | Pass / Pass | +80.5 | Lc 75: body text | Open in checker |
| Error text on surface#a21a1b on #fefefe | 7.71:1 | AA 4.5:1 | Pass / Pass | Pass / Pass | +84.7 | Lc 75: body text | Open in checker |
| Error badge label on fill#fcfcfc on #c8322e | 5.17:1 | AA 4.5:1 | Pass / Fail | Pass / Pass | −78.4 | Lc 75: body text | Open in checker |
| Info text on background#2274af on #f7f7f7 | 4.68:1 | AA 4.5:1 | Pass / Fail | Pass / Pass | +69.5 | Lc 60: larger content text | Open in checker |
| Info text on surface#2274af on #fefefe | 4.97:1 | AA 4.5:1 | Pass / Fail | Pass / Pass | +73.7 | Lc 60: larger content text | Open in checker |
| Info badge label on fill#fcfcfc on #1377b9 | 4.68:1 | AA 4.5:1 | Pass / Fail | Pass / Pass | −76.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#eeeeee on #161616 | 15.59:1 | AAA 7:1 | Pass / Pass | Pass / Pass | −95.8 | Lc 75: body text | Open in checker |
| Text on surface#eeeeee on #202020 | 14.04:1 | AAA 7:1 | Pass / Pass | Pass / Pass | −94.6 | Lc 75: body text | Open in checker |
| Muted text on background#bebebe on #161616 | 9.73:1 | AA 4.5:1 | Pass / Pass | Pass / Pass | −66.5 | Lc 60: larger content text | Open in checker |
| Muted text on surface#bebebe on #202020 | 8.76:1 | AA 4.5:1 | Pass / Pass | Pass / Pass | −65.3 | Lc 60: larger content text | Open in checker |
| Primary as link text on background#9fb2ff on #161616 | 8.86:1 | AA 4.5:1 | Pass / Pass | Pass / Pass | −61.7 | Lc 60: larger content text | Open in checker |
| Primary as link text on surface#9fb2ff on #202020 | 7.98:1 | AA 4.5:1 | Pass / Pass | Pass / Pass | −60.5 | Lc 60: larger content text | Open in checker |
| Button label on primary#0d0d0d on #9fb2ff | 9.51:1 | AA 4.5:1 | Pass / Pass | Pass / Pass | +63.9 | Lc 60: larger content text | Open in checker |
| Accent text on background#ff9c5f on #161616 | 8.76:1 | AA 4.5:1 | Pass / Pass | Pass / Pass | −61.4 | Lc 60: larger content text | Open in checker |
| Accent text on surface#ff9c5f on #202020 | 7.89:1 | AA 4.5:1 | Pass / Pass | Pass / Pass | −60.2 | Lc 60: larger content text | Open in checker |
| Border on background#6b6b6b on #161616 | 3.39:1 | 3:1 (WCAG 1.4.11) | Fail / Fail | Pass / Fail | −24.3 | Below Lc 30 | Open in checker |
| Border on surface#6b6b6b on #202020 | 3.05:1 | 3:1 (WCAG 1.4.11) | Fail / Fail | Pass / Fail | −23.1 | Below Lc 30 | Open in checker |
| Focus ring on background#9fb2ff on #161616 | 8.86:1 | 3:1 (WCAG 1.4.11) | Pass / Pass | Pass / Pass | −61.7 | Lc 60: larger content text | Open in checker |
| Focus ring on surface#9fb2ff on #202020 | 7.98:1 | 3:1 (WCAG 1.4.11) | Pass / Pass | Pass / Pass | −60.5 | Lc 60: larger content text | Open in checker |
| Success text on background#6ce5b5 on #161616 | 11.64:1 | AA 4.5:1 | Pass / Pass | Pass / Pass | −77.0 | Lc 75: body text | Open in checker |
| Success text on surface#6ce5b5 on #202020 | 10.48:1 | AA 4.5:1 | Pass / Pass | Pass / Pass | −75.8 | Lc 75: body text | Open in checker |
| Success badge label on fill#0f0f0f on #3bcd9a | 9.47:1 | AA 4.5:1 | Pass / Pass | Pass / Pass | +64.6 | Lc 60: larger content text | Open in checker |
| Warning text on background#ffbc56 on #161616 | 10.84:1 | AA 4.5:1 | Pass / Pass | Pass / Pass | −72.7 | Lc 60: larger content text | Open in checker |
| Warning text on surface#ffbc56 on #202020 | 9.76:1 | AA 4.5:1 | Pass / Pass | Pass / Pass | −71.5 | Lc 60: larger content text | Open in checker |
| Warning badge label on fill#0f0f0f on #e9a11d | 8.74:1 | AA 4.5:1 | Pass / Pass | Pass / Pass | +60.6 | Lc 60: larger content text | Open in checker |
| Error text on background#f66d62 on #161616 | 6.27:1 | AA 4.5:1 | Pass / Fail | Pass / Pass | −46.5 | Lc 45: headlines and large text | Open in checker |
| Error text on surface#f66d62 on #202020 | 5.65:1 | AA 4.5:1 | Pass / Fail | Pass / Pass | −45.3 | Lc 45: headlines and large text | Open in checker |
| Error badge label on fill#0f0f0f on #ff7a6d | 7.53:1 | AA 4.5:1 | Pass / Pass | Pass / Pass | +54.2 | Lc 45: headlines and large text | Open in checker |
| Info text on background#71bfff on #161616 | 9.13:1 | AA 4.5:1 | Pass / Pass | Pass / Pass | −63.4 | Lc 60: larger content text | Open in checker |
| Info text on surface#71bfff on #202020 | 8.22:1 | AA 4.5:1 | Pass / Pass | Pass / Pass | −62.2 | Lc 60: larger content text | Open in checker |
| Info badge label on fill#0f0f0f on #61b9ff | 9.02:1 | AA 4.5:1 | Pass / Pass | Pass / Pass | +62.1 | 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.2 | 26.0 | 39.0 | 31.7 | Shown only |
| success / error | 28.5 | 16.6 | 6.5 | 33.0 | Yes |
| success / info | 17.1 | 16.2 | 15.2 | 3.2 | Shown only |
| warning / error | 31.8 | 42.0 | 37.4 | 22.6 | Shown only |
| warning / info | 40.0 | 34.2 | 44.5 | 31.2 | Shown only |
| error / info | 30.3 | 24.1 | 21.6 | 33.0 | Shown only |
Fills as simulated:Normal visionProtanopiaDeuteranopiaTritanopia
| Pair | Normal vision | Protanopia | Deuteranopia | Tritanopia | Held to 6 |
|---|---|---|---|---|---|
| success / warning | 20.9 | 11.8 | 15.5 | 27.5 | Shown only |
| success / error | 28.8 | 15.3 | 6.4 | 31.3 | Yes |
| success / info | 17.7 | 15.2 | 14.3 | 3.8 | Shown only |
| warning / error | 13.3 | 13.2 | 10.5 | 5.5 | Shown only |
| warning / info | 28.5 | 26.0 | 28.7 | 26.2 | Shown only |
| error / info | 28.3 | 21.8 | 20.8 | 29.7 | Shown only |
Fills as simulated:Normal visionProtanopiaDeuteranopiaTritanopia
Why these colours
The primary is an indigo at OKLCH hue 275 with fairly high chroma, 0.17. Indigo reads as dependable and is not a colour most shoppers associate with an error or warning, which keeps Add to basket distinct. White labels reach AA on it with room to spare.
The accent is a strong orange at hue 45 and chroma 0.17, kept for sale badges and countdowns, where energy is wanted. In the light theme the verified text-form orange is a deep burnt tone; the bright form appears only as a fill behind dark text. The neutrals have no tint, so product photography keeps true colours around it, which matters when shoppers judge the colour of a garment.
The generator solved 50 pairs (25 light, 25 dark), and all of them meet their target on the raw WCAG ratio. The tightest is success badge label on fill in the light theme at 4.55:1 against a target of 4.5:1. After gamut mapping to sRGB the light primary keeps 100% of the requested chroma; hue was held throughout.
How to use it
- Indicate stock with text such as In stock or Only 3 left, using the success or warning colour as reinforcement.
- Make the sale price the strong text colour and the original price the muted colour with a strikethrough and a visually hidden label.
- Reserve the accent orange for promotions so it keeps its meaning; use the primary for the purchase action.
- Mark invalid card or address fields with the error colour, an icon and a message that names the field and fix.
- Do not rely on swatch colour alone for variant choice; name the colour, since many shoppers cannot tell similar tones apart.
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: #f7f7f7;
--color-surface: #fefefe;
--color-text: #1b1b1b;
--color-text-muted: #585858;
--color-primary: #4b53c2;
--color-primary-foreground: #fcfcfc;
--color-accent: #b33c00;
--color-border: #8e8e8e;
--color-focus-ring: #3e44b1;
--color-success: #008158;
--color-success-solid: #008558;
--color-success-solid-foreground: #fcfcfc;
--color-warning: #a16300;
--color-warning-solid: #ffba44;
--color-warning-solid-foreground: #0f0f0f;
--color-error: #a21a1b;
--color-error-solid: #c8322e;
--color-error-solid-foreground: #fcfcfc;
--color-info: #2274af;
--color-info-solid: #1377b9;
--color-info-solid-foreground: #fcfcfc;
}
.dark {
--color-background: #161616;
--color-surface: #202020;
--color-text: #eeeeee;
--color-text-muted: #bebebe;
--color-primary: #9fb2ff;
--color-primary-foreground: #0d0d0d;
--color-accent: #ff9c5f;
--color-border: #6b6b6b;
--color-focus-ring: #9fb2ff;
--color-success: #6ce5b5;
--color-success-solid: #3bcd9a;
--color-success-solid-foreground: #0f0f0f;
--color-warning: #ffbc56;
--color-warning-solid: #e9a11d;
--color-warning-solid-foreground: #0f0f0f;
--color-error: #f66d62;
--color-error-solid: #ff7a6d;
--color-error-solid-foreground: #0f0f0f;
--color-info: #71bfff;
--color-info-solid: #61b9ff;
--color-info-solid-foreground: #0f0f0f;
}
/* oklch() where supported: the same colours, unclipped values of the hex above. */
@supports (color: oklch(0 0 0)) {
:root {
--color-background: oklch(0.976 0.000 0.0);
--color-surface: oklch(0.997 0.000 0.0);
--color-text: oklch(0.222 0.000 0.0);
--color-text-muted: oklch(0.460 0.000 0.0);
--color-primary: oklch(0.500 0.171 275.2);
--color-primary-foreground: oklch(0.991 0.000 0.0);
--color-accent: oklch(0.5217 0.1643 39.84);
--color-border: oklch(0.647 0.000 0.0);
--color-focus-ring: oklch(0.450 0.170 274.8);
--color-success: oklch(0.5333 0.1163 162.37);
--color-success-solid: oklch(0.545 0.122 160.9);
--color-success-solid-foreground: oklch(0.991 0.000 0.0);
--color-warning: oklch(0.555 0.122 67.9);
--color-warning-solid: oklch(0.8335 0.1508 76.88);
--color-warning-solid-foreground: oklch(0.168 0.000 0.0);
--color-error: oklch(0.4603 0.1706 26.95);
--color-error-solid: oklch(0.551 0.187 27.1);
--color-error-solid-foreground: oklch(0.991 0.000 0.0);
--color-info: oklch(0.540 0.120 245.0);
--color-info-solid: oklch(0.5501 0.1324 245.13);
--color-info-solid-foreground: oklch(0.991 0.000 0.0);
}
.dark {
--color-background: oklch(0.200 0.000 0.0);
--color-surface: oklch(0.244 0.000 0.0);
--color-text: oklch(0.949 0.000 0.0);
--color-text-muted: oklch(0.802 0.000 0.0);
--color-primary: oklch(0.779 0.112 272.9);
--color-primary-foreground: oklch(0.159 0.000 0.0);
--color-accent: oklch(0.783 0.141 51.1);
--color-border: oklch(0.528 0.000 0.0);
--color-focus-ring: oklch(0.779 0.112 272.9);
--color-success: oklch(0.839 0.130 164.9);
--color-success-solid: oklch(0.759 0.143 165.0);
--color-success-solid-foreground: oklch(0.168 0.000 0.0);
--color-warning: oklch(0.839 0.140 75.1);
--color-warning-solid: oklch(0.7605 0.1539 75.30);
--color-warning-solid-foreground: oklch(0.168 0.000 0.0);
--color-error: oklch(0.700 0.171 27.0);
--color-error-solid: oklch(0.732 0.165 27.5);
--color-error-solid-foreground: oklch(0.168 0.000 0.0);
--color-info: oklch(0.780 0.120 245.0);
--color-info-solid: oklch(0.760 0.132 244.8);
--color-info-solid-foreground: oklch(0.168 0.000 0.0);
}
}Tailwind CSS v4 @theme
@theme {
/* light */
--color-background: oklch(0.976 0.000 0.0); /* #f7f7f7 */
--color-surface: oklch(0.997 0.000 0.0); /* #fefefe */
--color-text: oklch(0.222 0.000 0.0); /* #1b1b1b */
--color-text-muted: oklch(0.460 0.000 0.0); /* #585858 */
--color-primary: oklch(0.500 0.171 275.2); /* #4b53c2 */
--color-primary-foreground: oklch(0.991 0.000 0.0); /* #fcfcfc */
--color-accent: oklch(0.5217 0.1643 39.84); /* #b33c00 */
--color-border: oklch(0.647 0.000 0.0); /* #8e8e8e */
--color-focus-ring: oklch(0.450 0.170 274.8); /* #3e44b1 */
--color-success: oklch(0.5333 0.1163 162.37); /* #008158 */
--color-success-solid: oklch(0.545 0.122 160.9); /* #008558 */
--color-success-solid-foreground: oklch(0.991 0.000 0.0); /* #fcfcfc */
--color-warning: oklch(0.555 0.122 67.9); /* #a16300 */
--color-warning-solid: oklch(0.8335 0.1508 76.88); /* #ffba44 */
--color-warning-solid-foreground: oklch(0.168 0.000 0.0); /* #0f0f0f */
--color-error: oklch(0.4603 0.1706 26.95); /* #a21a1b */
--color-error-solid: oklch(0.551 0.187 27.1); /* #c8322e */
--color-error-solid-foreground: oklch(0.991 0.000 0.0); /* #fcfcfc */
--color-info: oklch(0.540 0.120 245.0); /* #2274af */
--color-info-solid: oklch(0.5501 0.1324 245.13); /* #1377b9 */
--color-info-solid-foreground: oklch(0.991 0.000 0.0); /* #fcfcfc */
/* dark: use as dark:bg-background-dark, or remap under a .dark selector */
--color-background-dark: oklch(0.200 0.000 0.0); /* #161616 */
--color-surface-dark: oklch(0.244 0.000 0.0); /* #202020 */
--color-text-dark: oklch(0.949 0.000 0.0); /* #eeeeee */
--color-text-muted-dark: oklch(0.802 0.000 0.0); /* #bebebe */
--color-primary-dark: oklch(0.779 0.112 272.9); /* #9fb2ff */
--color-primary-foreground-dark: oklch(0.159 0.000 0.0); /* #0d0d0d */
--color-accent-dark: oklch(0.783 0.141 51.1); /* #ff9c5f */
--color-border-dark: oklch(0.528 0.000 0.0); /* #6b6b6b */
--color-focus-ring-dark: oklch(0.779 0.112 272.9); /* #9fb2ff */
--color-success-dark: oklch(0.839 0.130 164.9); /* #6ce5b5 */
--color-success-solid-dark: oklch(0.759 0.143 165.0); /* #3bcd9a */
--color-success-solid-foreground-dark: oklch(0.168 0.000 0.0); /* #0f0f0f */
--color-warning-dark: oklch(0.839 0.140 75.1); /* #ffbc56 */
--color-warning-solid-dark: oklch(0.7605 0.1539 75.30); /* #e9a11d */
--color-warning-solid-foreground-dark: oklch(0.168 0.000 0.0); /* #0f0f0f */
--color-error-dark: oklch(0.700 0.171 27.0); /* #f66d62 */
--color-error-solid-dark: oklch(0.732 0.165 27.5); /* #ff7a6d */
--color-error-solid-foreground-dark: oklch(0.168 0.000 0.0); /* #0f0f0f */
--color-info-dark: oklch(0.780 0.120 245.0); /* #71bfff */
--color-info-solid-dark: oklch(0.760 0.132 244.8); /* #61b9ff */
--color-info-solid-foreground-dark: oklch(0.168 0.000 0.0); /* #0f0f0f */
}shadcn/ui variables (:root and .dark)
:root {
--background: oklch(0.976 0.000 0.0);
--foreground: oklch(0.222 0.000 0.0);
--card: oklch(0.997 0.000 0.0);
--card-foreground: oklch(0.222 0.000 0.0);
--popover: oklch(0.997 0.000 0.0);
--popover-foreground: oklch(0.222 0.000 0.0);
--primary: oklch(0.500 0.171 275.2);
--primary-foreground: oklch(0.991 0.000 0.0);
--secondary: oklch(0.997 0.000 0.0);
--secondary-foreground: oklch(0.222 0.000 0.0);
--muted: oklch(0.997 0.000 0.0);
--muted-foreground: oklch(0.460 0.000 0.0);
--accent: oklch(0.997 0.000 0.0);
--accent-foreground: oklch(0.222 0.000 0.0);
--destructive: oklch(0.551 0.187 27.1);
--destructive-foreground: oklch(0.991 0.000 0.0);
--border: oklch(0.647 0.000 0.0);
--input: oklch(0.647 0.000 0.0);
--ring: oklch(0.450 0.170 274.8);
--success: oklch(0.545 0.122 160.9);
--success-foreground: oklch(0.991 0.000 0.0);
--warning: oklch(0.8335 0.1508 76.88);
--warning-foreground: oklch(0.168 0.000 0.0);
--info: oklch(0.5501 0.1324 245.13);
--info-foreground: oklch(0.991 0.000 0.0);
--brand-accent: oklch(0.5217 0.1643 39.84);
}
.dark {
--background: oklch(0.200 0.000 0.0);
--foreground: oklch(0.949 0.000 0.0);
--card: oklch(0.244 0.000 0.0);
--card-foreground: oklch(0.949 0.000 0.0);
--popover: oklch(0.244 0.000 0.0);
--popover-foreground: oklch(0.949 0.000 0.0);
--primary: oklch(0.779 0.112 272.9);
--primary-foreground: oklch(0.159 0.000 0.0);
--secondary: oklch(0.244 0.000 0.0);
--secondary-foreground: oklch(0.949 0.000 0.0);
--muted: oklch(0.244 0.000 0.0);
--muted-foreground: oklch(0.802 0.000 0.0);
--accent: oklch(0.244 0.000 0.0);
--accent-foreground: oklch(0.949 0.000 0.0);
--destructive: oklch(0.732 0.165 27.5);
--destructive-foreground: oklch(0.168 0.000 0.0);
--border: oklch(0.528 0.000 0.0);
--input: oklch(0.528 0.000 0.0);
--ring: oklch(0.779 0.112 272.9);
--success: oklch(0.759 0.143 165.0);
--success-foreground: oklch(0.168 0.000 0.0);
--warning: oklch(0.7605 0.1539 75.30);
--warning-foreground: oklch(0.168 0.000 0.0);
--info: oklch(0.760 0.132 244.8);
--info-foreground: oklch(0.168 0.000 0.0);
--brand-accent: oklch(0.783 0.141 51.1);
}Design tokens (DTCG-style JSON)
{
"color": {
"light": {
"background": {
"$type": "color",
"$value": "oklch(0.976 0.000 0.0)",
"$description": "sRGB #f7f7f7"
},
"surface": {
"$type": "color",
"$value": "oklch(0.997 0.000 0.0)",
"$description": "sRGB #fefefe"
},
"text": {
"$type": "color",
"$value": "oklch(0.222 0.000 0.0)",
"$description": "sRGB #1b1b1b"
},
"text-muted": {
"$type": "color",
"$value": "oklch(0.460 0.000 0.0)",
"$description": "sRGB #585858"
},
"primary": {
"$type": "color",
"$value": "oklch(0.500 0.171 275.2)",
"$description": "sRGB #4b53c2"
},
"primary-foreground": {
"$type": "color",
"$value": "oklch(0.991 0.000 0.0)",
"$description": "sRGB #fcfcfc"
},
"accent": {
"$type": "color",
"$value": "oklch(0.5217 0.1643 39.84)",
"$description": "sRGB #b33c00"
},
"border": {
"$type": "color",
"$value": "oklch(0.647 0.000 0.0)",
"$description": "sRGB #8e8e8e"
},
"focus-ring": {
"$type": "color",
"$value": "oklch(0.450 0.170 274.8)",
"$description": "sRGB #3e44b1"
},
"success": {
"$type": "color",
"$value": "oklch(0.5333 0.1163 162.37)",
"$description": "sRGB #008158"
},
"success-solid": {
"$type": "color",
"$value": "oklch(0.545 0.122 160.9)",
"$description": "sRGB #008558"
},
"success-solid-foreground": {
"$type": "color",
"$value": "oklch(0.991 0.000 0.0)",
"$description": "sRGB #fcfcfc"
},
"warning": {
"$type": "color",
"$value": "oklch(0.555 0.122 67.9)",
"$description": "sRGB #a16300"
},
"warning-solid": {
"$type": "color",
"$value": "oklch(0.8335 0.1508 76.88)",
"$description": "sRGB #ffba44"
},
"warning-solid-foreground": {
"$type": "color",
"$value": "oklch(0.168 0.000 0.0)",
"$description": "sRGB #0f0f0f"
},
"error": {
"$type": "color",
"$value": "oklch(0.4603 0.1706 26.95)",
"$description": "sRGB #a21a1b"
},
"error-solid": {
"$type": "color",
"$value": "oklch(0.551 0.187 27.1)",
"$description": "sRGB #c8322e"
},
"error-solid-foreground": {
"$type": "color",
"$value": "oklch(0.991 0.000 0.0)",
"$description": "sRGB #fcfcfc"
},
"info": {
"$type": "color",
"$value": "oklch(0.540 0.120 245.0)",
"$description": "sRGB #2274af"
},
"info-solid": {
"$type": "color",
"$value": "oklch(0.5501 0.1324 245.13)",
"$description": "sRGB #1377b9"
},
"info-solid-foreground": {
"$type": "color",
"$value": "oklch(0.991 0.000 0.0)",
"$description": "sRGB #fcfcfc"
}
},
"dark": {
"background": {
"$type": "color",
"$value": "oklch(0.200 0.000 0.0)",
"$description": "sRGB #161616"
},
"surface": {
"$type": "color",
"$value": "oklch(0.244 0.000 0.0)",
"$description": "sRGB #202020"
},
"text": {
"$type": "color",
"$value": "oklch(0.949 0.000 0.0)",
"$description": "sRGB #eeeeee"
},
"text-muted": {
"$type": "color",
"$value": "oklch(0.802 0.000 0.0)",
"$description": "sRGB #bebebe"
},
"primary": {
"$type": "color",
"$value": "oklch(0.779 0.112 272.9)",
"$description": "sRGB #9fb2ff"
},
"primary-foreground": {
"$type": "color",
"$value": "oklch(0.159 0.000 0.0)",
"$description": "sRGB #0d0d0d"
},
"accent": {
"$type": "color",
"$value": "oklch(0.783 0.141 51.1)",
"$description": "sRGB #ff9c5f"
},
"border": {
"$type": "color",
"$value": "oklch(0.528 0.000 0.0)",
"$description": "sRGB #6b6b6b"
},
"focus-ring": {
"$type": "color",
"$value": "oklch(0.779 0.112 272.9)",
"$description": "sRGB #9fb2ff"
},
"success": {
"$type": "color",
"$value": "oklch(0.839 0.130 164.9)",
"$description": "sRGB #6ce5b5"
},
"success-solid": {
"$type": "color",
"$value": "oklch(0.759 0.143 165.0)",
"$description": "sRGB #3bcd9a"
},
"success-solid-foreground": {
"$type": "color",
"$value": "oklch(0.168 0.000 0.0)",
"$description": "sRGB #0f0f0f"
},
"warning": {
"$type": "color",
"$value": "oklch(0.839 0.140 75.1)",
"$description": "sRGB #ffbc56"
},
"warning-solid": {
"$type": "color",
"$value": "oklch(0.7605 0.1539 75.30)",
"$description": "sRGB #e9a11d"
},
"warning-solid-foreground": {
"$type": "color",
"$value": "oklch(0.168 0.000 0.0)",
"$description": "sRGB #0f0f0f"
},
"error": {
"$type": "color",
"$value": "oklch(0.700 0.171 27.0)",
"$description": "sRGB #f66d62"
},
"error-solid": {
"$type": "color",
"$value": "oklch(0.732 0.165 27.5)",
"$description": "sRGB #ff7a6d"
},
"error-solid-foreground": {
"$type": "color",
"$value": "oklch(0.168 0.000 0.0)",
"$description": "sRGB #0f0f0f"
},
"info": {
"$type": "color",
"$value": "oklch(0.780 0.120 245.0)",
"$description": "sRGB #71bfff"
},
"info-solid": {
"$type": "color",
"$value": "oklch(0.760 0.132 244.8)",
"$description": "sRGB #61b9ff"
},
"info-solid-foreground": {
"$type": "color",
"$value": "oklch(0.168 0.000 0.0)",
"$description": "sRGB #0f0f0f"
}
}
}
}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 #4B53C2 in the OKLCH picker →Build a tonal scale →Check a pair
FAQ
- Does the accent work for sale badges?
- The badge fill and label are a verified pair, shown as the warning badge row. The orange accent is also verified as text on page and card colours.
- What about product photos on tinted backgrounds?
- The neutrals are untinted so photography is not colour-shifted. Photo contrast is not covered by this palette; test labels placed on images separately.
- Is dark mode useful for a store?
- Some shoppers prefer it at night, and some need it. Every role has a verified dark value, and the export snippets include both themes.
- Can I use the shadcn block in my storefront?
- If your storefront uses shadcn/ui, paste the :root and .dark block. The names match the variables used on this site's shadcn themes.