Tailwind moves configuration from JavaScript to CSS using the @theme
directive and CSS variables.
Defining Custom Colors
Add colors in your CSS file using @theme
:
@import 'tailwindcss';
@theme {
--color-brand: #5b21b6;
--color-neon-pink: oklch(71.7% 0.25 360);
--color-neon-lime: oklch(91.5% 0.258 129);
}
This generates utilities like bg-brand
, text-neon-pink
, etc.
Overriding Default Colors
Replace specific colors:
@theme {
--color-blue-500: #1e40af; /* Override default blue-500 */
}
Clear entire color groups:
@theme {
--color-gray-*: initial; /* Remove all default grays */
--color-gray-50: #f8fafc;
--color-gray-100: #f1f5f9;
/* Define your custom grays */
}
Start from scratch:
@import 'tailwindcss/preflight';
@import 'tailwindcss/utilities';
@theme {
--color-*: initial; /* Remove ALL defaults */
/* Define your entire palette */
}
Using Colors as CSS Variables
Theme colors are exposed as CSS variables:
In Custom CSS
.custom-element {
background: var(--color-brand);
border-color: var(--color-neon-pink);
}
In Arbitrary Values
...
...
<!-- Long form -->
<div class="bg-[var(--color-neon-pink)]">...</div>
<!-- Shorthand (v4) -->
<div class="text-(--color-brand)">...</div>
Opacity Modifiers
Works with all color definitions:
50% opacity
75% opacity
20% opacity
<div class="bg-brand/50">50% opacity</div>
<div class="text-neon-pink/75">75% opacity</div>
<div class="border-[var(--color-custom)]/20">20% opacity</div>
Important Tailwind 4 Changes
Border Color Default
...
Explicit color needed
<!-- v3: defaulted to gray-200 -->
<div class="border">...</div>
<!--Tailwind 4: defaults to currentColor -->
<div class="border border-gray-200">Explicit color needed</div>
Ring Color Default
...
Explicit width and color
<!-- v3: 3px blue ring -->
<div class="ring">...</div>
<!--Tailwind 4: 1px currentColor -->
<div class="ring-3 ring-blue-500">Explicit width and color</div>
Dynamic Theming
CSS variables enable runtime theme switching:
@theme {
--color-surface: white;
--color-text: black;
}
[data-theme='dark'] {
--color-surface: #1a1a1a;
--color-text: white;
}
Automatically themed
<body data-theme="dark">
<div class="bg-surface text-text">Automatically themed</div>
</body>
Best Practices
- Use semantic names for brand colors:
--color-primary
,--color-accent
- Group related colors:
--color-gray-*
,--color-brand-*
- Leverage OKLCH for consistent palettes
- Document your colors with comments in
@theme
- Test opacity modifiers with your custom colors