Published on

You’ve probably heard that a very alpha version of Tailwind CSS v4 has been open sourced.

It’s not ready for production yet, but let’s tale a look at how it simplifies setting up a multi-theme strategy.

Theme configuration in CSS

One of the key new features in v4 is the ability to customize the theme directly in a CSS file instead of the Tailwind config.

Theme values (like colors, font sizes, spacing) can be defined with CSS variables like so:

/* app/styles.css */
@import 'tailwindcss' @theme {
  --color-primary: #aab9ff;
}

This is the equivalent of doing the following in Tailwind CSS v3:

// tailwind.config.ts
export default {
  theme: {
    colors: {
      primary: '#aab9ff',
    },
  },
}

In v4, the CSS variables are also exposed in your CSS output, which means you can “consume” those variables anywhere you need it:

<div class="bg-[--color-primary]"></div>

Multi-Theme Strategy in Tailwind

If you’ve taken my Multi-Theme Strategy workshop, you know that the procedure to define themable CSS variables was somewhat convoluted:

1. Define CSS variables holding R G B channels

:root {
  --primary: 170 185 255;
}

2. Compose that CSS variable with an rgb() function + <alpha-value> to add a color in the tailwind.config.ts file

theme: {
  extend: {
    colors: {
      primary: rbg(var(--primary) / <alpha-value>)
    }
  }
}

Honestly, this is quite painful. And forces you to define your colors in a weird, custom format (space-separated R G and B channels).


It’s way easier in Tailwind v4

Tailwind CSS v4 drastically simplifies the process of defining themable CSS variables:

1. Define a CSS variable with any color format, in CSS

@theme {
  --color-primary: #aab9ff;
}

2. That’s it! there is no step 2.

You can redefine this variable value at different theme scopes like so:

@theme {
  --color-primary: #aab9ff;
}

@layer base {
  [data-theme='ocean'] {
    --color-primary: #aab9ff;
  }

  [data-theme='rainforest'] {
    --color-primary: #56d0a0;
  }

  [data-theme='candy'] {
    --color-primary: #f9a8d4;
  }
}

And that’s all you need to apply themable classes to your HTML:

Minimal theming strategy in Tailwind v4

Minimal theming strategy in Tailwind v4

Wait, why can’t I just use the bg-primary class?

Well, using the bg-primary class directly would retrieve the actual HEX color defined in the @theme block:

CSS class hover showing the HEX value consumption

Utilities generated from the @theme block will consume the actual color value defined.

If you want to use “normal” utility classes like bg-primary directly, you can go an extra step:

Mapping the @theme CSS variables to another variable

You can define another CSS variable which will be consumed by the @theme theme variable:

Advanced theming setup

Theming setup to support bg-primary directly

This time, the bg-primary class will consume a CSS variable that changes for every theme scope.

No <alpha-value> needed!

Did you notice we didn’t have to construct an rgb() color composed with the <alpha-value>?

Opacity support straight up works with HEX or any other color format, because Tailwind CSS v4 is using color-mix() to compose the opacity:

Opacity support without alpha-value

Opacity support without using Tailwind’s internal <alpha-value>.


Updating the Multi-Theme Strategy workshop

This all means that some parts of the Multi-Theme Strategy workshop could be simplified.

I say could, because right now, there is no Plugin API support for Tailwind CSS v4. There isn’t even support for the tailwind.config file.

In other words, you can manually define themable CSS variables, but you can’t automate the process of passing a JSON theme to a plugin and have it generate all the theming parts for you.

When that becomes available, I’ll definitely look into upgrading the strategy to the best possible approach in v4!

Have a great day ❤️


illustration of the Pro Tailwind corgi mascot

I'm building Pro Tailwind, an advanced-level course on Tailwind CSS. We dig into techniques that scale up with your team. Sign up today!