OKLCH in Tailwind CSS v4: Colors, Palette and @theme
Tailwind CSS v4 defines its entire default color palette in OKLCH instead of RGB. This guide covers what changed, how to write OKLCH colors in a v4 @theme block, and how to migrate custom colors from a v3 config without breaking class names.
Last updated: 2026-10-07 · Maintained by the OKLCH Colors team
When Did Tailwind Start Using OKLCH?
With Tailwind CSS v4.0, released January 22, 2025. The v4.0 release notes state: "We've upgraded the entire default color palette from rgb to oklch, taking advantage of the wider gamut to make the colors more vivid in places where we were previously limited by the sRGB color space."
So from v4.0 onward, every value behind bg-blue-500, text-red-500 and the rest of the default palette is an oklch() color. v3.x and earlier stayed on RGB. The utility class names did not change — only the color notation underneath.
Verified source: Tailwind CSS — v4.0 release blog post
Why OKLCH Instead of RGB?
Two reasons, both stated in the release notes: wider gamut and perceptual structure. OKLCH is not confined to sRGB, so on wide-gamut Display-P3 displays the same color can render more vividly than its RGB definition ever allowed. And because lightness in OKLCH is perceptually uniform, a 500-to-600 step in the palette moves by a consistent amount of perceived brightness — the property that makes generated scales feel evenly spaced.
- Same classes, richer output: no class renames —
bg-emerald-500keeps working, the value behind it changed notation. - Ready for wide gamut: when a v4 project lands on a P3 display, the palette can actually show the extra color.
- Consistent lightness ramps: the 50–950 steps line up with perceptual brightness rather than channel math.
Writing OKLCH Colors in @theme
Tailwind v4 moved configuration into CSS. Custom colors live in the @theme block under the --color-{name} namespace, and any value the browser accepts as a color — including oklch() — can be assigned:
@import "tailwindcss";
@theme {
--color-brand-500: oklch(62.3% 0.188 259.8);
--color-brand-600: oklch(55% 0.18 259.8);
--color-surface: oklch(98% 0.005 250);
}Utilities are generated automatically:
<div class="bg-brand-500 text-surface">
<a class="hover:bg-brand-600">Because the token is an ordinary custom property, every downstream Tailwind feature — opacity modifiers like bg-brand-500/50, dark: variants, and color-mix() under the hood — operates on the OKLCH value directly. A HEX value still works in the same slot; writing oklch() simply keeps the whole theme in one color space.
Familiar Palette Colors, Converted to OKLCH
Build-Time GeneratedIf you are carrying custom colors forward from v3, start from the value you already have. These well-known default-palette hex values are converted below by the same engine every converter on this site uses — copy the oklch() column straight into a v4 @theme block:
| Color | Token | HEX (v3) | OKLCH (v4) |
|---|---|---|---|
| red-500 | #ef4444 | oklch(63.7% 0.208 25.3) | |
| orange-500 | #f97316 | oklch(70.5% 0.187 47.6) | |
| amber-500 | #f59e0b | oklch(76.9% 0.165 70.1) | |
| emerald-500 | #10b981 | oklch(69.6% 0.149 162.5) | |
| sky-400 | #38bdf8 | oklch(75.3% 0.139 232.7) | |
| blue-500 | #3b82f6 | oklch(62.3% 0.188 259.8) | |
| violet-500 | #8b5cf6 | oklch(60.6% 0.219 292.7) | |
| pink-500 | #ec4899 | oklch(65.6% 0.212 354.3) |
The v3 column shows the published sRGB hex of each token; the v4 column is this site's build-time conversion of that same color.
Migrating Custom Colors from v3
v4's upgrade guide covers the tooling side (the config moves from tailwind.config.js into CSS). For the colors themselves, the recipe is small and mechanical:
- Move each color from the v3
theme.extend.colorsentry into an@theme--color-{name}variable. - Convert the value with a converter (HEX → OKLCH, RGB → OKLCH, or HSL → OKLCH) and paste the
oklch()result. Keeping the same name means no class changes anywhere. - Leave names that contain theme breakpoints or
DEFAULTfor a pass on their own — they map to slightly different variable patterns in v4. - Spot-check opacity modifiers:
bg-brand/40should still render — v4 resolves it throughcolor-mix()regardless of the source notation.
Verified source: Tailwind CSS — Upgrade guide (v3 → v4)
Frequently Asked Questions
Does Tailwind CSS v4 use OKLCH for every color?
The entire default palette is defined in OKLCH as of v4.0. Your own colors can be any notation — Tailwind accepts HEX, RGB, HSL or OKLCH in @theme — but writing them as oklch() keeps one color space throughout the project.
Do my class names change when I upgrade?
No. bg-blue-500 is still bg-blue-500; only the value behind it changed from an RGB to an OKLCH definition. Class renames in v4 come from other parts of the upgrade, not from the color-space switch.
Can I still use HEX values in Tailwind v4?
Yes. HEX remains valid anywhere a color is accepted. Converting to OKLCH is optional — the benefit is perceptually uniform lightness for derived colors and gamut headroom, not a requirement for the framework to work.
Do opacity modifiers work with OKLCH colors?
Yes. Utilities like bg-brand-500/50 work the same way regardless of the token's notation — v4 resolves opacity through color-mix(), which handles OKLCH values natively.
Why do my v4 colors look slightly different on my new laptop?
If the display is wide-gamut (many recent laptops are), OKLCH colors can show more vivid reds, greens and blues than the same color rendered from its old RGB value on an sRGB screen. That headroom is exactly what the v4 release notes describe as the motivation for the switch.