Overview
Tailwind v4 (the 4.x line, current as of 2026) configures through CSS, scans source files automatically, and requires Safari 16.4+, Chrome 111+, or Firefox 128+. This page is the hub; tokens, dark mode, variants, plugins, responsive design, and migration have their own pages.
Install with the Vite plugin or PostCSS
Use @tailwindcss/vite on Vite-based stacks and @tailwindcss/postcss elsewhere; the CLI also works.
npm install tailwindcss @tailwindcss/vite@import "tailwindcss";Configure in CSS, not JavaScript
Define tokens with @theme; each token becomes a CSS variable and a utility. A tailwind.config.js is not detected; load one only through @config, which ignores corePlugins, safelist, and separator.
@import "tailwindcss";
@theme {
--color-brand: oklch(0.72 0.18 264);
--font-display: "Schibsted Grotesk", system-ui, sans-serif;
}This yields bg-brand and font-display. See tailwind-theme. Tailwind emits real cascade layers (theme, base, components, utilities), so unlayered CSS beats utilities; see css-cascade-layers.
Compose with utilities; extract at the third use
Keep utilities inline. Extract a component when the same combination appears in three or more places and should change as a unit. Avoid @apply for your own components, because it hides the contract inside a stylesheet. Use it for markup you cannot annotate, such as a CMS body or a third-party widget. In CSS modules and Vue or Svelte <style> blocks, start the file with @reference "../app.css"; so @apply can see the theme. For the comparison with scoped stylesheets, see tailwind-vs-css-modules.
Treat arbitrary values as a missing token
Use bracket syntax for one-off values and add a token when the same value appears a third time.
<div class="w-[412px] grid-cols-[1fr_500px_2fr] bg-(--brand) [mask-type:luminance] [&:nth-child(3)]:font-bold">- Underscores stand in for spaces inside brackets.
[property:value]sets any CSS property without a named utility, such as[content-visibility:auto].- Reference CSS variables with parentheses:
bg-(--brand). The v3 formbg-[--brand]no longer works. - Keep arbitrary values out of shared components; they should read tokens.
- Prefer
var()insidecalc()so the value keeps its link to a token:mt-[calc(var(--header-h)+1rem)].
Write complete class names
Tailwind scans files as plain text, so a concatenated class such as `bg-${color}-600` is never generated. Map props to complete strings instead:
const colorVariants = { blue: "bg-blue-600 text-white", red: "bg-red-500 text-white" };
<button className={colorVariants[color]} />;Register sources the scanner skips (it ignores .gitignored paths, node_modules, binary files, and CSS files) with @source "../node_modules/@acme/ui";. Safelist generated classes with @source inline("{hover:,}bg-red-{50,{100..900..100},950}");; the safelist config key is gone.
Set up tooling once
- Prettier:
prettier-plugin-tailwindcsssorts classes. On v4 you must set"tailwindStylesheet": "./src/app.css"to point at your CSS entry, and the plugin must be last inplugins. - ESLint:
eslint-plugin-tailwindcss4.x supports Tailwind v4 and requiressettings.tailwindcss.cssConfigPathpointing at the same CSS entry.no-contradicting-classnamecatchesp-2 p-3on one element, andno-unnecessary-arbitrary-valueflags brackets that match a built-in token. - Editor: install
bradlc.vscode-tailwindcssfor autocomplete, hover CSS, and lint. Add helper names totailwindCSS.classFunctions(for examplecn,cva) and custom props totailwindCSS.classAttributesso strings outsideclassandclassNameget completions. - DevTools: a struck-through property means another rule wins, usually unlayered CSS. A missing property means the class was never generated.
Avoid common pitfalls
- Unlayered resets beat utilities. A global
* { margin: 0 }outside any layer overrides every utility. Put it in@layer base. - Custom layer order. Declare it before the import, for example
@layer theme, base, vendor, components, utilities;. A list placed after@import "tailwindcss"appends new layers afterutilities, so they win. - Tokens missing. A
@themeblock only takes effect in the CSS file Tailwind processes (the one with@import "tailwindcss") or a file it imports; a separately bundled stylesheet generates no utilities. - Preprocessors. Sass, Less, and Stylus are not supported; Tailwind handles imports, prefixes, and nesting.
- Plugins. Container queries are built in; typography and forms remain official plugins; see tailwind-plugins.