Tailwind CSS Handbook v4.3

Colors

The v4 oklch palette, the opacity modifier, every colour-accepting utility, and how to define an accessible palette with @theme.

Tailwind v4 ships a default palette of 25 colour families in the OKLCH colour space, each with 11 steps from 50 to 950.

The palette#

GroupFamilies
Warmred orange amber yellow
Greenlime green emerald teal
Bluecyan sky blue indigo
Purple/pinkviolet purple fuchsia pink rose
Neutralslate gray zinc neutral stone
Muted v4.2mauve olive mist taupe

Plus black, white, transparent, current and inherit.

Loading preview…

Choosing a neutral#

The five greys differ in temperature. Pick one and stay with it.

FamilyUndertonePairs well with
slateCool blueBlues, indigos
graySlightly coolAlmost anything
zincNeutralMinimal, technical UI
neutralPure greyPhotography, art direction
stoneWarmOranges, ambers, editorial

OKLCH#

The palette is defined in oklch():

CSS
--color-red-500: oklch(63.7% 0.237 25.331);
--color-blue-600: oklch(54.6% 0.245 262.881);

OKLCH is perceptually uniform, so 500 looks equally bright across every family — something the old hex palette could not guarantee. It also reaches colours outside sRGB on wide-gamut displays.

Where colours apply#

UtilityProperty
text-*color
bg-*background-color
border-*border-color
border-t-*, border-x-*Per-side border colour
divide-*Borders between children
outline-*outline-color
ring-*Box-shadow ring
inset-ring-*Inset ring
shadow-*Coloured box shadow
inset-shadow-*Inset shadow colour
drop-shadow-*Coloured drop shadow v4.1
text-shadow-*Text shadow colour v4.1
decoration-*text-decoration-color
accent-*Native form control accent
caret-*Text cursor
fill-* / stroke-*SVG
from-* / via-* / to-*Gradient stops
placeholder:text-*Placeholder text
selection:bg-*Highlighted text
scrollbar-thumb-* / scrollbar-track-*Scrollbars v4.3

Opacity modifier#

Append / and a percentage to any colour utility.

HTML
<div class="bg-sky-500/50">50%</div>
<div class="bg-pink-500/[71.37%]">Arbitrary</div>
<div class="bg-cyan-400/(--my-alpha)">From a variable</div>

It compiles to color-mix(in oklab, …), so it works with any colour — including CSS variables and currentColor.

/ vs opacity-*#

bg-black/50opacity-50
AffectsJust that colourThe whole element, including children
Creates a stacking contextNoYes
Right forTranslucent surfaces, overlaysFading an entire element

The stacking-context difference matters — see Overflow & Layering.

Special values#

ValueMeaning
transparentFully transparent
currentInherits currentColor
inheritInherits the parent's value
black / whitePure

text-current is how you make an SVG follow its parent's text colour:

HTML
<button class="text-indigo-600 hover:text-indigo-500">
  <svg class="size-4 fill-current">…</svg>
  Continue
</button>

Customising#

Add colours#

CSS
@theme {
  --color-brand-50:  oklch(0.97 0.02 264);
  --color-brand-500: oklch(0.62 0.19 264);
  --color-brand-900: oklch(0.35 0.14 264);
}

Any colour syntax works — #4f46e5, rgb(79 70 229), hsl(243 75% 59%) — but OKLCH gives the most even scales.

Override a default#

CSS
@theme {
  --color-gray-500: oklch(0.55 0.02 260);
}

Remove families you do not use#

CSS
@theme {
  --color-lime-*: initial;
  --color-fuchsia-*: initial;
}

Replace the palette entirely#

CSS
@theme {
  --color-*: initial;
  --color-white: #fff;
  --color-black: #000;
  --color-ink: oklch(0.25 0.02 264);
  --color-brand: oklch(0.62 0.19 264);
}

Now only your colours exist — a strong guardrail on a design system.

Semantic aliases#

CSS
@theme {
  --color-success: var(--color-emerald-600);
  --color-danger: var(--color-red-600);
  --color-warning: var(--color-amber-500);
}
HTML
<p class="text-danger">Something went wrong.</p>

Accessibility#

WCAG 2.1 AA requires:

  • 4.5:1 for body text
  • 3:1 for large text (18.66px bold, or 24px)
  • 3:1 for UI components and meaningful graphics

Approximate ratios against white:

ColourRatioBody text?
gray-400~2.8:1✗
gray-500~4.6:1✓
gray-600~7.0:1✓
indigo-500~4.6:1✓ (borderline)
indigo-600~6.3:1✓
yellow-400~1.4:1✗ — never for text on white

Common patterns#

Tinted status badges#

Loading preview…

The pattern — 50 background, 700 text, 600/20 ring — works for every family.

Translucent overlays#

HTML
<div class="absolute inset-0 bg-gray-900/60 backdrop-blur-sm"></div>

Colour with --alpha() in custom CSS#

CSS
.highlight {
  background-color: --alpha(var(--color-yellow-300) / 35%);
}

Common mistakes#

  • Using *-opacity-* utilities. Removed in v4.
  • Building class names from variables. ` bg-${color}-500 ` produces nothing — map to full class names.
  • opacity-50 where bg-black/50 was meant. It fades the text too, and creates a stacking context.
  • Mixing neutral families. slate borders with zinc text looks subtly off.
  • Light grey text. text-gray-400 on white fails contrast. Use 500 or darker.