Starting from TailwindCSS v4, the CSS-first configuration is preferred, meaning the init process and the tailwind.config.js file have been removed.

  • What's breaking changes from TailwindCSS v4
  • New CSS-first configuration from TailwindCSS v4
  • Removed @tailwind directives
  • Deprecated: Sass, Less and Stylus preprocessors support

Customize theme with CSS-first directives

In a CSS-first configuration, several directives are available. For theme customization, you can primarily use the @theme directive:

@import "tailwindcss";

@theme {
  --font-display: "Satoshi", "sans-serif";
  --breakpoint-3xl: 120rem;
  --color-avocado-100: oklch(0.99 0 0);
  --color-avocado-200: oklch(0.98 0.04 113.22);
  --color-avocado-300: oklch(0.94 0.11 115.03);
  --color-avocado-400: oklch(0.92 0.19 114.08);
  --color-avocado-500: oklch(0.84 0.18 117.33);
  --color-avocado-600: oklch(0.53 0.12 118.34);
  --ease-fluid: cubic-bezier(0.3, 0, 0, 1);
  --ease-snappy: cubic-bezier(0.2, 0, 0, 1);
  /* ... */
}
  • @theme directive

Theme variables are defined in namespaces and each namespace corresponds to one or more utility class or variant APIs.

  • Theme variable namespaces
  • Default theme variable reference

Set dark directive with CSS-first

Starting from v4, a new @custom-variant directive is introduced, allowing you to customize the behavior of dark: or create your own custom variants, such as coffee:.

  • @custom-variant directive
  • @variant directive

document.querySelector('button').addEventListener('click', () => {
  document.documentElement.classList.toggle('dark');
});
<script src="https://unpkg.com/@tailwindcss/browser"></script>
<style type="text/tailwindcss">
/* changed the behavior of dark: (default: based on prefers-color-scheme) to work based on the presence of the .dark parent class */
@custom-variant dark (&:where(.dark, .dark *));

@theme {
  --color-pink: #eb6bd8;
}

@layer theme {
  :root, :host {
    @variant dark {
      --color-pink: #8e0d7a;
    }
  }
}
</style>

<button class="size-20 bg-pink dark:text-white">Click Here</button>
<div class="w-50 h-12 bg-purple-200 dark:bg-purple-900 dark:text-white">
  Lorem Ipsum
</div>

Additionally, without JS, it's possible to detect whether the system prefers light or dark mode by default, and integrate this into the dark: variant behavior. For this, your light/dark toggle needs to support three states: system/light/dark. You'll also need an extra .system class, but the dark: variant can work the same way with both .system and .dark classes:

  • Manual dark mode toggle, but by default it should follow the system scheme

How to declare dark or more themes in TailwindCSS v4

Following the dark example, an unlimited number of variants and themes can be declared.

document.querySelector('#toggle-dark').addEventListener('click', () => {
  document.documentElement.classList.toggle('dark');
  document.documentElement.classList.remove('coffee');
});

document.querySelector('#toggle-coffee').addEventListener('click', () => {
  document.documentElement.classList.toggle('coffee');
  document.documentElement.classList.remove('dark');
});
<script src="https://unpkg.com/@tailwindcss/browser"></script>
<style type="text/tailwindcss">
@custom-variant dark (&:where(.dark, .dark *));
@custom-variant coffee (&:where(.coffee, .coffee *));

@theme {
  --color-pink: #eb6bd8;
  --color-tsunami: #77b4ea;
}

@layer theme {
  :root, :host {
    @variant dark {
      --color-pink: #8e0d7a;
      --color-tsunami: #0d84ec;
    }
    @variant coffee {
      --color-pink: #a67ca8;
      --color-tsunami: #b57913;
    }
  }
}
</style>

<div class="mb-4">
  <button id="toggle-dark" class="px-4 py-2 bg-sky-600 hover:bg-sky-950 text-white cursor-pointer rounded-lg">Toggle Dark</button>
  <button id="toggle-coffee" class="px-4 py-2 bg-amber-600 hover:bg-amber-950 text-white  cursor-pointer rounded-lg">Toggle Coffee</button>
</div>

<button class="size-20 bg-pink dark:text-white coffee:text-amber-50">Hello World</button>
<div class="w-50 h-12 bg-tsunami dark:text-white coffee:text-orange-200">
  Lorem Ipsum
</div>

References:

  • How to override theme variables in TailwindCSS v4 - @theme vs @layer theme vs :root
  • When should I use * and when should I use :root, :host as the parent selector?
  • How @variant dark can be combined with @theme in a CSS-first configuration to override dark mode colors
  • Should I use @theme or @theme inline?
  • How can I safely introduce the use of light-dark() without increasing the minimum browser version requirement?

Disable dark mode, use light: instead of dark::

  • TailwindCSS: How to do a light mode only modification?
  • How to disable dark mode in TailwindCSS 4
Answer from rozsazoltan on Stack Overflow
🌐
Tailwind CSS
tailwindcss.com › docs › customizing-colors
Colors - Core concepts - Tailwind CSS
Use --color-*: initial to completely disable all of the default colors and define your own custom color palette: ... @import "tailwindcss";@theme { --color-*: initial; --color-white: #fff; --color-purple: #3f3cbb; --color-midnight: #121063; ...
🌐
Tailwind Colors
tailwindcolor.com
Tailwind Colors v4 | OKLCH Color Palette
Tailwind CSS Colors v4 now uses OKLCH for a more vivid, modern color palette. Upgraded from RGB, it uses the wider P3 gamut for richer hues and better contrast. Elevate your designs with enhanced accessibility and future-proof colors.
Discussions

Tailwind 4 confusion about colours
You can still define your own color variables https://tailwindcss.com/docs/colors#customizing-your-colors Also check out how shadcn has implemented light / dark theming and naming More on reddit.com
🌐 r/tailwindcss
27
0
April 19, 2025
reactjs - How to use custom color themes in TailwindCSS v4 - Stack Overflow
This is a piece of code for v3,and I can customize the color of the dark theme instead of using black like this: ... Can't find detailed tailwind.config.js documentation. ... Starting from TailwindCSS v4, a CSS-first configuration is preferred. Check my answer to see what this means. More on stackoverflow.com
🌐 stackoverflow.com
How to semantically name your colors in tailwind v4?
Version 4 of Tailwind prefers using CSS directly to define your theme config: @import "tailwindcss"; @theme { --color-brand: var(--color-blue-500); } If you need to use JS, then remember to use the extend prop on your theme, otherwise you'll wipe out all of the other colours. More on reddit.com
🌐 r/tailwindcss
7
5
December 10, 2024
Upgraded to Tailwind V4 and all my custom colors stopped working...
You know that you don’t HAVE to use oklch in Tailwind 4, right? More on reddit.com
🌐 r/tailwindcss
12
6
April 11, 2025
People also ask

Can I still use tailwind.config.js?
Yes, but it’s now optional for colors. Use it for other settings like breakpoints, plugins, or JIT safelists.
🌐
tailkits.com
tailkits.com › blog
Tailwind v4 Colors: Add & Customize Fast | Tailkits
Can I use arbitrary color values like bg-[#1e40af] in v4?
Yes—JIT arbitrary‑value syntax is unchanged, and the compiler still tree‑shakes those single‑use utilities.
🌐
tailkits.com
tailkits.com › blog
Tailwind v4 Colors: Add & Customize Fast | Tailkits
Is there a limit to how many custom colors I can add?
No practical limit; the compiler generates utilities for every variable you declare, though more tokens slightly increase build size.
🌐
tailkits.com
tailkits.com › blog
Tailwind v4 Colors: Add & Customize Fast | Tailkits
🌐
Medium
medium.com › @dvasquez.422 › custom-colours-in-tailwind-css-v4-acc3322cd2da
Custom Colours in Tailwind CSS v4 | by David Vasquez | Medium
August 7, 2025 - Custom Colours in Tailwind CSS v4 Tailwind CSS recently released version 4 of their framework. There’s definitely been some changes and one of them is the way we do custom colours. I ran into a …
🌐
Reddit
reddit.com › r/tailwindcss › tailwind 4 confusion about colours
r/tailwindcss on Reddit: Tailwind 4 confusion about colours
April 19, 2025 -

Hi so I'm trying out tailwind in a new react project I'm working on. After a lot of wrangling with ChatGPT I realised that it doesn't seem to know much about tailwind 4 other than it exists and I had to revert to stack overflow to figure out how to get it to work by using @themes in my config.

The thing I'm confused about though is in the tailwind 3 examples I was being given you could set things like bg-primary and bg-primaryDark in one place which makes sense and is useful as I can use it all over and update it quickly to try out different colour schemes.

Whereas in Tailwind 4 the examples seem to suggest I should be using things like bg-cyan-500 everywhere which obviously means I have to change them all if I want to update it. Seems like an anti pattern so I just wanted to check whether I've misunderstood how I should be approaching this?

🌐
Tailscan
tailscan.com › colors
Tailwind CSS Colors
This cheatsheet contains all the default Tailwind CSS colors, including all hex, hsl, rgb and new Tailwind v4 oklch color values. Never forget any Tailwind CSS color again!
🌐
Tailcolors
tailcolors.com
Tailwind v4 Color Palette • tailcolors
Copy any Tailwind color with our beautiful Tailwind 4 color palette. Click to copy any HEX, OKLCH, or Tailwind 4 color class.
Find elsewhere
🌐
DEV Community
dev.to › matfrana › the-mystery-of-tailwind-colors-v4-hjh
The Mystery of Tailwind Colors (v4) - DEV Community
February 20, 2025 - You'll discover the fundamentals ... v4 with several new features. A key change is that colors are now defined using OKLCH notation, such as oklch(0.685 0.169 237.323)....
Top answer
1 of 3
37

Starting from TailwindCSS v4, the CSS-first configuration is preferred, meaning the init process and the tailwind.config.js file have been removed.

  • What's breaking changes from TailwindCSS v4
  • New CSS-first configuration from TailwindCSS v4
  • Removed @tailwind directives
  • Deprecated: Sass, Less and Stylus preprocessors support

Customize theme with CSS-first directives

In a CSS-first configuration, several directives are available. For theme customization, you can primarily use the @theme directive:

@import "tailwindcss";

@theme {
  --font-display: "Satoshi", "sans-serif";
  --breakpoint-3xl: 120rem;
  --color-avocado-100: oklch(0.99 0 0);
  --color-avocado-200: oklch(0.98 0.04 113.22);
  --color-avocado-300: oklch(0.94 0.11 115.03);
  --color-avocado-400: oklch(0.92 0.19 114.08);
  --color-avocado-500: oklch(0.84 0.18 117.33);
  --color-avocado-600: oklch(0.53 0.12 118.34);
  --ease-fluid: cubic-bezier(0.3, 0, 0, 1);
  --ease-snappy: cubic-bezier(0.2, 0, 0, 1);
  /* ... */
}
  • @theme directive

Theme variables are defined in namespaces and each namespace corresponds to one or more utility class or variant APIs.

  • Theme variable namespaces
  • Default theme variable reference

Set dark directive with CSS-first

Starting from v4, a new @custom-variant directive is introduced, allowing you to customize the behavior of dark: or create your own custom variants, such as coffee:.

  • @custom-variant directive
  • @variant directive

document.querySelector('button').addEventListener('click', () => {
  document.documentElement.classList.toggle('dark');
});
<script src="https://unpkg.com/@tailwindcss/browser"></script>
<style type="text/tailwindcss">
/* changed the behavior of dark: (default: based on prefers-color-scheme) to work based on the presence of the .dark parent class */
@custom-variant dark (&:where(.dark, .dark *));

@theme {
  --color-pink: #eb6bd8;
}

@layer theme {
  :root, :host {
    @variant dark {
      --color-pink: #8e0d7a;
    }
  }
}
</style>

<button class="size-20 bg-pink dark:text-white">Click Here</button>
<div class="w-50 h-12 bg-purple-200 dark:bg-purple-900 dark:text-white">
  Lorem Ipsum
</div>

Additionally, without JS, it's possible to detect whether the system prefers light or dark mode by default, and integrate this into the dark: variant behavior. For this, your light/dark toggle needs to support three states: system/light/dark. You'll also need an extra .system class, but the dark: variant can work the same way with both .system and .dark classes:

  • Manual dark mode toggle, but by default it should follow the system scheme

How to declare dark or more themes in TailwindCSS v4

Following the dark example, an unlimited number of variants and themes can be declared.

document.querySelector('#toggle-dark').addEventListener('click', () => {
  document.documentElement.classList.toggle('dark');
  document.documentElement.classList.remove('coffee');
});

document.querySelector('#toggle-coffee').addEventListener('click', () => {
  document.documentElement.classList.toggle('coffee');
  document.documentElement.classList.remove('dark');
});
<script src="https://unpkg.com/@tailwindcss/browser"></script>
<style type="text/tailwindcss">
@custom-variant dark (&:where(.dark, .dark *));
@custom-variant coffee (&:where(.coffee, .coffee *));

@theme {
  --color-pink: #eb6bd8;
  --color-tsunami: #77b4ea;
}

@layer theme {
  :root, :host {
    @variant dark {
      --color-pink: #8e0d7a;
      --color-tsunami: #0d84ec;
    }
    @variant coffee {
      --color-pink: #a67ca8;
      --color-tsunami: #b57913;
    }
  }
}
</style>

<div class="mb-4">
  <button id="toggle-dark" class="px-4 py-2 bg-sky-600 hover:bg-sky-950 text-white cursor-pointer rounded-lg">Toggle Dark</button>
  <button id="toggle-coffee" class="px-4 py-2 bg-amber-600 hover:bg-amber-950 text-white  cursor-pointer rounded-lg">Toggle Coffee</button>
</div>

<button class="size-20 bg-pink dark:text-white coffee:text-amber-50">Hello World</button>
<div class="w-50 h-12 bg-tsunami dark:text-white coffee:text-orange-200">
  Lorem Ipsum
</div>

References:

  • How to override theme variables in TailwindCSS v4 - @theme vs @layer theme vs :root
  • When should I use * and when should I use :root, :host as the parent selector?
  • How @variant dark can be combined with @theme in a CSS-first configuration to override dark mode colors
  • Should I use @theme or @theme inline?
  • How can I safely introduce the use of light-dark() without increasing the minimum browser version requirement?

Disable dark mode, use light: instead of dark::

  • TailwindCSS: How to do a light mode only modification?
  • How to disable dark mode in TailwindCSS 4
2 of 3
3

light-dark() CSS function

With light-dark(), a color can be tied to the color-scheme. Based on the color-scheme, the browser selects the color corresponding to the current scheme. This essentially simplifies the declaration of light and dark themes, allowing it to be done in a single place, within @theme.

@theme {
  --color-pink: light-dark(#eb6bd8, #8e0d7a);
  --color-tsunami: light-dark(#77b4ea, #0d84ec);
}

Attention: TailwindCSS is shipped under the hood with LightningCSS. While LightningCSS does provide a fallback for older browsers to replace light-dark(), TailwindCSS does not apply it due to an open issue, meaning it is not available. TailwindCSS officially guarantees support starting from Baseline 2023, but light-dark() is a CSS function that was only stably introduced in Baseline 2024. This means that if you use it, your minimum browser version requirements will rise to the level where light-dark() was introduced. More details:

  • https://tailwindcss.com/docs/compatibility (Baseline 2023)
  • https://caniuse.com/?search=light-dark (Baseline 2024)
  • Question for light-dark() using in older browsers (In the question, the functionality is explained with many references and version numbers)

document.querySelector('button').addEventListener('click', () => {
  document.documentElement.classList.toggle('dark');
});
<script src="https://unpkg.com/@tailwindcss/browser"></script>
<style type="text/tailwindcss">
/* changed the behavior of dark: (default: based on prefers-color-scheme) to work based on the presence of the .dark parent class */
@custom-variant dark (&:where(.dark, .dark *));

/* WARNING: This way, instead of Chrome 111, at least Chrome 123 will be required, and instead of Safari 16.4, Safari 17.5 will be needed for it to work. */
@theme {
  --color-pink: light-dark(#eb6bd8, #8e0d7a);
  --color-tsunami: light-dark(#77b4ea, #0d84ec);
}

* {
  color-scheme: light; /* apply "light" (first) color from light-dark() */
  
  @variant dark {
    color-scheme: dark; /* apply "dark" (second) color from light-dark() */
  }
}
</style>

<button class="size-20 bg-pink dark:text-white">Click Here</button>
<div class="w-50 h-12 bg-tsunami dark:text-white">
  Lorem Ipsum
</div>

var(--tw-light, ...) var(--tw-dark, ...) alternative

The previously mentioned question has an answer that explains how the behavior of light-dark() can be replicated with a little extra work. This way, you can avoid raising the minimum browser version requirement in your project.

  • How can I safely introduce the use of light-dark() without increasing the minimum browser version requirement?
@theme inline {
  --color-pink: var(--tw-light, #eb6bd8) var(--tw-dark, #8e0d7a);
  --color-tsunami: var(--tw-light, #77b4ea) var(--tw-dark, #0d84ec);
}

Note: Since @theme ships the given value into a global variable, the value cannot be a variable itself; otherwise, CSS cannot properly track the fallback values. Therefore, you should always use @theme inline. @theme inline does not embed the values into a global variable. However, it isn't necessary, since later on we don't want to override the color for other themes, as each theme can be declared locally in a single line.

document.querySelector('button').addEventListener('click', () => {
  document.documentElement.classList.toggle('dark');
});
<script src="https://unpkg.com/@tailwindcss/browser"></script>
<style type="text/tailwindcss">
/* changed the behavior of dark: (default: based on prefers-color-scheme) to work based on the presence of the .dark parent class */
@custom-variant dark (&:where(.dark, .dark *));

/* NOTE: It still works starting from Chrome 111 and Safari 16.4. */
@theme inline {
  --color-pink: var(--tw-light, #eb6bd8) var(--tw-dark, #8e0d7a);
  --color-tsunami: var(--tw-light, #77b4ea) var(--tw-dark, #0d84ec);
}

* {
  color-scheme: light;
  --tw-light: initial;
  --tw-dark: ;
  
  @variant dark {
    color-scheme: dark;
    --tw-light: ;
    --tw-dark: initial;
  }
}
</style>

<button class="size-20 bg-pink dark:text-white">Click Here</button>
<div class="w-50 h-12 bg-tsunami dark:text-white">
  Lorem Ipsum
</div>

🌐
Tailwind CSS
tailwindcss.com › blog › tailwindcss-v4
Tailwind CSS v4.0 - Tailwind CSS
One of the biggest changes in Tailwind CSS v4.0 is the shift from configuring your project in JavaScript to configuring it in CSS. Instead of a tailwind.config.js file, you can configure all of your customizations directly in the CSS file where you import Tailwind, giving you one less file to worry about in your project: ... @import "tailwindcss";@theme { --font-display: "Satoshi", "sans-serif"; --breakpoint-3xl: 1920px; --color-avocado-100: oklch(0.99 0 0); --color-avocado-200: oklch(0.98 0.04 113.22); --color-avocado-300: oklch(0.94 0.11 115.03); --color-avocado-400: oklch(0.92 0.19 114.08); --color-avocado-500: oklch(0.84 0.18 117.33); --color-avocado-600: oklch(0.53 0.12 118.34); --ease-fluid: cubic-bezier(0.3, 0, 0, 1); --ease-snappy: cubic-bezier(0.2, 0, 0, 1); /* ...
🌐
Tailkits
tailkits.com › blog
Tailwind v4 Colors: Add & Customize Fast | Tailkits
August 31, 2025 - Tailwind v4 rewired the way colors are defined, shipped, and overridden. Everything is now CSS‑first and token‑driven: every design token becomes a custom property at build‑time, and new @theme blocks replace most of the old tailwind.config.js ...
🌐
Figma
figma.com › community › file › 1433327789445151857 › tailwind-colors-v4-2
Tailwind Colors v4.2 | Figma
1 month ago - The latest version of Tailwind v4's new colors as Figma variables—featuring a redesigned, more vivid color palette that takes advantage of modern P3 displays. Now includes new Taupe, Mauve, Mist, and Olive palettes added in v4.2. All credit ...
🌐
Flowbite
flowbite.com › docs › customize › colors
Tailwind CSS Colors - Flowbite
Customize the default colors of Flowbite using the default color variables from the Tailwind CSS framework · Since the Tailwind v4 update the default and recommended way of managing and using colors is with native CSS variables.
🌐
Tailwind CSS
tailwindcss.com › docs › color
color - Typography - Tailwind CSS
v4.2 · ⌘KCtrl KDocsBlogShowcaseSponsorPlus · Typography · color · Typography · Utilities for controlling the text color of an element. Show more · Use utilities like text-blue-600 and text-sky-400 to control the text color of an element: ...
🌐
Medium
ckriswinarto.medium.com › how-to-add-custom-colors-in-tailwind-css-v4-with-vite-example-6a8c37b46324
How to Add Custom Colors in Tailwind CSS v4 (with Vite Example) | by Candra Kriswinarto | Medium
October 29, 2024 - How to Add Custom Colors in Tailwind CSS v4 (with Vite Example) Tailwind CSS v4 introduces a simpler way to work with design tokens like colors. But what if you want to use your own custom color …
🌐
Tailwind CSS
tailwindcss.com › docs › color-scheme
color-scheme - Interactivity - Tailwind CSS
v4.2 · ⌘KCtrl KDocsBlogShow... controlling the color scheme of an element. Use utilities like scheme-light and scheme-light-dark to control how element should be rendered: Try switching your system color scheme to see ...
🌐
Laravel News
laravel-news.com › home › new colors added in tailwind css v4.2
New Colors Added in Tailwind CSS v4.2 - Laravel News
February 19, 2026 - Tailwind CSS v4.2.0 adds a new webpack plugin, four new default color palettes, a full set of logical property utilities for block-direction spacing and borders, and new inline/block size utilities that map directly to CSS logical sizing properties.
🌐
shadcn/ui
ui.shadcn.com › colors
Tailwind Colors in Every Format - shadcn/ui
The complete Tailwind color palette in HEX, RGB, HSL, CSS variables, and classes. Ready to copy and paste into your project.
🌐
TWColors
tailwindcolor.tools › home › tailwind colors
All 242 Tailwind CSS Colors - Complete Color Palette Reference | TWColors
Browse the complete Tailwind CSS v4 color palette with all 22 color families and 11 shades (50-950). Search, filter, and copy hex codes, RGB, OKLCH values instantly. Free color reference for developers.