When I saw Tailwind v4 move configuration into CSS, my first question was whether the class names would need to change too. Values previously defined in tailwind.config.js can now live in CSS inside @theme.
The same brand color in v3 and v4#
Suppose the brand color is dark blue and headings use Georgia. These examples use identical values, with each project already set up for its Tailwind version.
v3: extend the JavaScript configuration.
// tailwind.config.js
module.exports = {
content: ["./index.html", "./src/**/*.{html,js,ts,jsx,tsx,vue}"],
theme: {
extend: {
colors: { brand: "#173f76" },
fontFamily: { display: ["Georgia", "serif"] },
},
},
};extend adds colors and fonts while preserving the defaults. content tells Tailwind where to look for class names. The CSS entry also needs these directives:
/* app.css */
@tailwind base;
@tailwind components;
@tailwind utilities;v4: put the equivalent configuration in CSS.
/* app.css */
@import "tailwindcss";
@theme {
--color-brand: #173f76;
--font-display: Georgia, serif;
}v4 automatically detects source files in ordinary projects, so this example does not need a content list. The brand color maps to --color-brand, and the font maps to --font-display.
The markup stays the same in both versions.
<h1 class="text-brand font-display">Latest articles</h1>
<button class="bg-brand text-white">Subscribe</button>The heading uses the brand color and Georgia font; the button uses the brand background with white text. For this example, configuration moves while the class names stay unchanged.
One distinction matters: @theme is processed by Tailwind during the build. Putting a variable in :root alone will not create utilities such as bg-brand. The color is also available to ordinary CSS through var(--color-brand), which is the part I find particularly convenient.