Disabling default theme entirely
To completely disable the default theme and use only custom values, set --*: initial; within @theme. This removes all default utility classes driven by theme variables, leaving only utilities matching custom theme variables like static utilities (flex, object-cover).
Theme variables generated as CSS variables in output
All theme variables are turned into regular CSS variables in the compiled CSS output, placed in a :root selector. This makes design tokens available for reference in custom CSS, arbitrary values, and inline styles via var(--variable-name) syntax.
Defining animation keyframes within @theme
Define @keyframes rules for --animate-* theme variables within @theme to include them in generated CSS. For example, defining --animate-fade-in-scale: fade-in-scale 0.3s ease-out; with corresponding @keyframes fade-in-scale {} makes the animation available. To include @keyframes without adding an --animate-* theme variable, define them outside @theme.
Using inline option for theme variable references
When defining theme variables that reference other variables, use the inline option: @theme inline { --font-sans: var(--font-inter); }. This makes the utility class use the theme variable value instead of referencing the actual theme variable. Without inline, variable resolution can fail when the referenced variable isn't in scope at the point of utility definition.
Static theme option for generating all CSS variables
By default, only used CSS variables are generated in final CSS output. Use the static theme option (@theme static { ... }) to always generate all CSS variables, even unused ones.
Sharing theme variables across projects
Since theme variables are defined in CSS, they can be shared by placing them in a separate CSS file and importing with @import in each project. This works in monorepo setups or when publishing shared themes to NPM as third-party CSS files.
Tailwindcss import structure
Importing tailwindcss at the top of a CSS file includes @import "./theme.css" (layer theme), @import "./preflight.css" (layer base), and @import "./utilities.css" (layer utilities). The theme.css file contains the default theme variables including color palette, type scale, shadows, and fonts.
Using theme variables in custom CSS
Theme variables can be referenced in custom CSS using var(--variable-name) syntax to access design tokens. This is useful when styling content you don't control, like Markdown rendered from APIs or databases.
Using theme variables in arbitrary values
Theme variables can be used in arbitrary value utilities combined with calc() for dynamic calculations. For example, rounded-[calc(var(--radius-xl)-1px)] subtracts 1px from the radius-xl value.
Referencing theme variables in JavaScript
Theme variables can be referenced in JavaScript using CSS variable values directly. Use getComputedStyle(document.documentElement).getPropertyValue('--variable-name') to access resolved CSS variable values from the document root.
@import replaces @tailwind directives
In v4, replace the three @tailwind directives (base, components, utilities) with a single @import statement: @import "tailwindcss";
Prefix syntax changed
In v4, prefixes look like variants and are always at the beginning of the class name, separated by a colon (e.g., tw:flex, tw:bg-red-500, tw:hover:bg-red-600). Configure theme variables as if you aren't using a prefix, but the generated CSS variables will include the prefix to avoid conflicts (e.g., --tw-color-red-500).
theme() function uses CSS variable names
In v4, prefer using CSS variables directly instead of the theme() function (e.g., var(--color-red-500) instead of theme(colors.red.500)). For cases where theme() is still needed (like in media queries where CSS variables aren't supported), use CSS variable names instead of dot notation (e.g., theme(--breakpoint-xl) instead of theme(screens.xl)).
JavaScript config files require @config directive
In v4, JavaScript config files are no longer detected automatically. To use a JavaScript config file, load it explicitly with the @config directive: @config "../../tailwind.config.js";. Note: corePlugins, safelist, and separator options are not supported in v4.
@reference directive for scoped stylesheets
In v4, stylesheets bundled separately (CSS modules, Vue/Svelte <style> blocks, etc.) don't have access to theme variables, custom utilities, and custom variants. Use @reference "../../app.css"; to import them without duplicating CSS. Alternatively, use CSS variables directly instead of @apply for better performance.
ESM and TypeScript support in v3.3
Tailwind CSS v3.3 added support for configuring Tailwind in ES Module (ESM) syntax and TypeScript. The configuration can be written as an ESM module with export default syntax or as a TypeScript file with type annotations. When running npx tailwindcss init, the CLI detects if the project is an ES Module and automatically generates the config with the right syntax. Use the --esm flag to explicitly generate an ESM config file, or the --ts flag to generate a TypeScript config file.
ESM and TypeScript config examples for v3.3
ES Module config:
```javascript
/** @type {import('tailwindcss').Config} */
export default {
content: [],
theme: {
extend: {},
},
plugins: [],
};
```
TypeScript config:
```typescript
import type { Config } from 'tailwindcss'
export default {
content: [],
theme: {
extend: {},
},
plugins: [],
} satisfies Config
```
v3.3 uses jiti and Sucrase for transpilation
Tailwind CSS v3.3 handles on-the-fly transpilation of ESM and TypeScript config files using the jiti library under the hood, with Sucrase used to transpile the code for optimal performance while keeping the installation footprint small.
Source exclusion with @source not
The @source not directive allows you to exclude specific paths from Tailwind's class name scanning. This is useful when you have large directories that should not be scanned for class names. Example: @source not "./src/components/legacy";
Safelist utilities with @source inline()
The @source inline() directive forces Tailwind to generate specific class names that may not exist in source files. This replaces the safelist configuration option from previous versions. The input supports brace expansion for generating multiple classes. Example: @source inline("underline"); or @source inline("{hover:,}bg-red-{50,{100..900..100},950}");
Prevent class generation with @source not inline()
You can use @source not inline("classname") to specifically prevent Tailwind from generating certain class names, even if they are detected in source files. Example: @source not inline("container");