Blog

CSS-First Configuration in Tailwind v4

Where Did the Tailwind Config Go?

With version 4.0, Tailwind CSS made a big change: it removed the configuration file and made it possible to set up your whole theme and styling directly in CSS. The change gives developers a more flexible, modern setup.

In Tailwind 3.x, defining project-specific colors, fonts or spacing values meant creating a tailwind.config file:

// tailwind.config

module.exports = {
  theme: {
    extend: {
      colors: {
        brand: {
          100: '#EA6365',
          DEFAULT: '#FA7275'
        }
      }
    }
  }
}

Now tailwind.config isn't needed anymore; you can define everything in a CSS file instead.

With this approach you're not extending Tailwind's theme directly. Instead you define CSS variables and use them through Tailwind classes.

/* css file */
@import "tailwindcss";

@theme inline {
  --color-background: var(--background);
  --color-foreground: var(--foreground);
  /* ... */
  --color-border: var(--border);
  --color-primary: #FF0099;
  --color-secondary: #a1a1a1;
  /* ... */
  --padding-smallxx: 0.5rem;
  --padding-large: 1.5rem;
}

:root {
  --radius: 0.625rem;
  --background: oklch(1 0 0);
  --foreground: oklch(0.145 0 0);
  /* ... */
  --border: oklch(0.922 0 0);
}
<!-- and in your markup -->
<h2 className="bg-amber-50 font-extrablack text-secondary p-smallxx">How are you?</h2>

🎨 For example, you can combine Tailwind utility classes like .bg-background, .text-foreground and .border-border with @apply inside @layer base:

@layer base {
  * {
    @apply border-border outline-ring/50;
  }
  body {
    @apply bg-background text-foreground;
  }
}

Which means:

  • border-border → border-color: var(--border);
  • bg-background → background-color: var(--background);
  • text-foreground → color: var(--foreground);

In other words, Tailwind classes now reference CSS variables under the hood.

The old config was limited to Tailwind's theme. With the new approach everything is a CSS variable, so it's far more flexible and switching between modes is easy (for example .dark).

/* Define global CSS variables */
:root {
  --color-primary: #3490dc;      /* Blue */
  --color-secondary: #ffed4a;    /* Yellow */
  --color-background: #f8fafc;   /* Background */
  --color-foreground: #2d3748;   /* Text */
}

/* Variables that change the colors in dark mode */
.dark {
  --color-primary: #1d4ed8;      /* Dark blue */
  --color-secondary: #fbbf24;    /* Dark yellow */
  --color-background: #2d3748;   /* Dark background */
  --color-foreground: #f7fafc;   /* White text */
}

This makes automatic theme switching based on the user's system preference possible.

There's also new integration with modern CSS features:

  • Registering custom CSS properties with @property
  • Color mixing with color-mix()
/* Define the utility */
@layer utilities {
  .bg-mixed {
    background-color: color-mix(in srgb, #f00 50%, #00f 50%);
  }
}

/* usage:
<div className="bg-mixed">
  <h1 className="text-white text-3xl">Home</h1>
</div>
*/
  • Animation starting styles with @starting-style
  • Excluding specific states with the not-* variant
<!-- sets the background to green-500, but only when not in dark mode -->
<div class="not-dark:bg-green-500 bg-mixed p-10">
  <h1 class="text-white text-3xl">Home</h1>
</div>

🚀 Conclusion

Tailwind CSS v4.0 gives developers a more flexible, faster and more modern setup. Removing the config file and going CSS-first makes managing styles more intuitive and maintainable. If you want to explore these features yourself, take a look at the Tailwind CSS v4.0 announcement.

Happy coding 👨‍💻 🎉


Originally published in Turkish on Medium.