Cheatsheet
Tailwind CSS v4 quick reference
Version 4 moved configuration out of JavaScript and into CSS, so the first thing to relearn is the setup. After that: the theme namespaces that generate utilities, the utility groups you use hourly, every variant prefix, and the renames that break a v3 codebase on upgrade.
CSS first setup
There is no tailwind.config.js by default. One CSS file is the entry point, the theme, and the plugin list.
@import "tailwindcss";
/* Restrict scanning, then add back what you need. */
@source "./src";
@source not "./dist";
@source inline("bg-red-500 bg-green-500");
@theme {
--color-brand-500: oklch(0.72 0.14 165);
--font-display: "Inter", ui-sans-serif, system-ui, sans-serif;
--breakpoint-3xl: 120rem;
--spacing: 0.25rem;
}
/* Class based dark mode instead of the prefers-color-scheme default. */
@custom-variant dark (&:where(.dark, .dark *));
/* A first party utility, variant aware for free. */
@utility tab-4 {
tab-size: 4;
}
@layer components {
.btn-primary {
@apply rounded-lg bg-brand-500 px-6 py-3 font-semibold;
}
} | Directive | What it does |
|---|---|
| @import "tailwindcss" | Replaces the three v3 directives. Pulls in preflight, theme, and utilities. |
| @theme { ... } | Defines design tokens that generate utility classes and CSS variables at once. |
| @theme inline { ... } | Same, but inlines the value rather than referencing it. Needed when a token points at another variable. |
| @source "./src" | Adds a path to class detection. Pair with source(none) on the import to disable auto detection. |
| @source not "./dist" | Excludes a directory. Essential when build output is not gitignored. |
| @source inline("...") | Force generates classes that never appear literally in source, such as ones built at runtime. |
| @utility name { ... } | Registers a custom utility that works with every variant. The v4 replacement for a plugin. |
| @custom-variant name (...) | Defines your own variant prefix, including the class based dark mode selector. |
| @plugin "@tailwindcss/typography" | Loads a JavaScript plugin from CSS instead of from a config file. |
| @config "../tailwind.config.js" | Escape hatch that loads a legacy v3 config during a migration. |
| @reference "../app.css" | Makes theme values available inside a component style block without duplicating output. |
| @apply rounded-lg px-4 | Still supported. In a separate file or a component style block, add @reference first. |
Gotcha: Tailwind scans your source as plain text, so a class name assembled from fragments such as text-{color}-500 is never generated. Write complete class names, map them in an object, or list them in @source inline().
Theme namespaces
The prefix of a theme variable decides which family of utilities it generates. Define --color-mint-500 and you immediately have bg-mint-500, text-mint-500, border-mint-500, and the rest.
| Namespace | Generates |
|---|---|
| --color-* | bg-*, text-*, border-*, ring-*, fill-*, stroke-*, and every other color utility. |
| --font-* | Font family utilities such as font-sans and font-display. |
| --text-* | Font size utilities such as text-sm and text-xl. |
| --font-weight-* | font-bold, font-medium, and friends. |
| --tracking-* | Letter spacing utilities such as tracking-tight. |
| --leading-* | Line height utilities such as leading-relaxed. |
| --spacing | The single base unit. Every p-*, m-*, gap-*, w-* and h-* step is a multiple of it. |
| --breakpoint-* | Responsive variants such as sm: and a custom 3xl:. |
| --container-* | Container query variants such as @sm: plus width utilities such as max-w-md. |
| --radius-* | Border radius utilities such as rounded-lg. |
| --shadow-* | Box shadow utilities. Separate namespaces exist for inset-shadow-* and drop-shadow-*. |
| --blur-* | Blur filter utilities, which also feed backdrop-blur-*. |
| --aspect-* | Aspect ratio utilities such as aspect-video. |
| --ease-* | Transition timing functions such as ease-out. |
| --animate-* | Animation utilities. Declare the keyframes inside the same @theme block. |
| --perspective-* | 3D perspective utilities, new in v4. |
| --color-*: initial | Wipes an entire namespace so only your own tokens remain. |
| --*: initial | Wipes the whole default theme. Total control, total responsibility. |
Gotcha: theme variables must sit at the top level of @theme. They cannot be nested or wrapped in a media query. Values you want as plain CSS variables without generating utilities belong in :root instead.
Layout, spacing, and sizing
| Utility | CSS |
|---|---|
| flex / grid / block / hidden | display. hidden is display: none, not visibility. |
| p-4 px-6 py-3 pt-2 | padding, all sides then axis then single side. |
| m-4 mx-auto -mt-2 | margin. Prefix with a minus for negative values. |
| ps-4 pe-4 ms-2 me-2 | Logical inline start and end. Correct in right to left layouts. |
| w-full h-screen size-8 | width, height, and size-* which sets both at once. |
| min-w-0 max-w-7xl min-h-dvh | Constraints. dvh handles the mobile browser chrome correctly. |
| static relative absolute fixed sticky | position. |
| inset-0 top-4 -bottom-2 | Offsets. inset-0 is all four sides at zero. |
| z-10 z-50 | z-index. Arbitrary values work: z-[999]. |
| overflow-hidden overflow-x-auto | overflow. overflow-x-auto is the correct wrapper for a wide table. |
| space-y-4 | Margin between siblings. Prefer flex plus gap-4, which does not break on wrapping. |
| container | Max width matching the current breakpoint. In v4 it no longer centers or pads by itself. |
Flexbox and grid
| Utility | CSS |
|---|---|
| flex-row flex-col flex-wrap | flex-direction and flex-wrap. |
| items-center items-start items-baseline | align-items, across the cross axis. |
| justify-between justify-center | justify-content, along the main axis. |
| gap-4 gap-x-2 gap-y-6 | gap. Works in both flex and grid. |
| grow shrink-0 basis-1/3 | flex-grow, flex-shrink, flex-basis. Renamed from flex-grow-* in v4. |
| flex-1 flex-none | Shorthands: grow and shrink from zero basis, or neither. |
| order-first order-last order-2 | Visual reorder only. The DOM and tab order are unchanged. |
| grid-cols-3 grid-rows-2 | Equal fraction tracks. |
| grid-cols-[200px_1fr] | Arbitrary track list. Underscores stand in for spaces. |
| col-span-2 row-span-3 col-start-2 | Item placement across tracks. |
| grid-flow-dense | Backfills holes left by spanning items. |
| place-items-center | Centers on both axes in a grid. The shortest true centering. |
Gotcha: a flex child will not shrink below its content width unless you add min-w-0. That single class fixes most cases of a long string blowing out a flex layout.
Typography, color, and borders
| Utility | CSS |
|---|---|
| text-sm text-3xl | font-size, each step carrying a paired default line height. |
| text-base/7 | Font size with an explicit line height, using the slash modifier. |
| font-mono font-semibold italic | font-family, font-weight, font-style. |
| text-white text-brand-300 | color, from the --color-* namespace. |
| bg-black/50 | Color with opacity. This modifier replaced every bg-opacity-* utility. |
| bg-linear-to-r from-brand-500 to-brand-300 | Linear gradient. v4 renamed bg-gradient-to-* to bg-linear-to-*. |
| text-center truncate text-balance | Alignment, single line ellipsis, and balanced wrapping for headlines. |
| line-clamp-3 | Truncate after three lines. Built in since v3.3, no plugin needed. |
| wrap-break-word wrap-anywhere | overflow-wrap. Added in v4.1 for long URLs that break a layout. |
| text-shadow-sm text-shadow-lg | text-shadow, new in v4.1. |
| border border-2 border-t | border-width. The default color is currentColor in v4, not gray-200. |
| rounded-lg rounded-t-xl rounded-full | border-radius, all corners or one side. |
| ring-2 ring-brand-500 ring-offset-2 | Outline style box shadow. The bare ring utility is now 1px, not 3px. |
| shadow-sm shadow-xl inset-shadow-xs | box-shadow, outer and inset. |
Variant prefixes
Variants stack left to right and read outside in, so dark:md:hover:bg-brand-500 means dark mode, at md and up, on hover.
| Prefix | Applies when |
|---|---|
| sm: md: lg: xl: 2xl: | Min width 40rem, 48rem, 64rem, 80rem, 96rem. Mobile first: unprefixed is the small case. |
| max-md: | Below that breakpoint, for the rare desktop first exception. |
| min-[900px]: | One off breakpoint without adding a token. |
| @container then @md: | Container queries: size against the nearest marked ancestor rather than the viewport. |
| hover: focus: active: visited: | The classic interaction states. |
| focus-visible: focus-within: | Keyboard only focus, and focus anywhere inside. Use focus-visible for outlines. |
| disabled: checked: required: invalid: | Form control states, straight from the CSS pseudo classes. |
| first: last: odd: even: only: | Structural position among siblings. |
| empty: target: open: | No children, the URL fragment target, and an open details or dialog element. |
| group-hover: group-focus: | React to an ancestor marked with the group class. Name them: group/card and group-hover/card:. |
| peer-checked: peer-invalid: | React to a previous sibling marked with peer. Only works on earlier siblings. |
| has-[:checked]: | Style a parent based on its descendants, using the CSS has selector. |
| not-hover: not-first: | Negates any other variant. Added in v4. |
| data-[state=open]: aria-expanded: | Match a data or aria attribute. The standard bridge to headless UI libraries. |
| before: after: placeholder: selection: marker: | Pseudo elements. before and after set content: "" automatically. |
| dark: motion-reduce: print: rtl: | Media and direction variants. dark: follows prefers-color-scheme unless you redefine it. |
| *: **: | Style direct children or all descendants from the parent element. |
| supports-[display:grid]: | Feature query. Applies only when the browser supports that declaration. |
Gotcha: peer-* only reaches later siblings, because CSS has no previous sibling combinator. If the element you want to style comes first in the DOM, reorder it and use order-*, or move the state up and use group-*.
Renamed and removed since v3
| v3 | v4 |
|---|---|
| shadow-sm / shadow | shadow-xs / shadow-sm |
| drop-shadow-sm / drop-shadow | drop-shadow-xs / drop-shadow-sm |
| blur-sm / blur | blur-xs / blur-sm |
| backdrop-blur-sm / backdrop-blur | backdrop-blur-xs / backdrop-blur-sm |
| rounded-sm / rounded | rounded-xs / rounded-sm |
| outline-none | outline-hidden |
| ring | ring-3 |
| flex-shrink-* / flex-grow-* | shrink-* / grow-* |
| overflow-ellipsis | text-ellipsis |
| decoration-slice / decoration-clone | box-decoration-slice / box-decoration-clone |
| bg-opacity-50 and every *-opacity-* utility | bg-black/50 (the slash modifier) |
| tailwind.config.js | @theme in CSS, or @config for a legacy file |
| @tailwind base / components / utilities | @import "tailwindcss" |
| Default border color gray-200 | currentColor |
Gotcha: the border color change is the quiet one. Every border without an explicit color now inherits the text color, so a v3 layout can look fine in a build log and wrong in the browser. Run the official upgrade tool first, then read the diff.
Keep going
Not sold on utility classes? Tailwind vs CSS Modules makes the case for both sides, and the CSS tool directory lists the alternatives.
These classes usually live inside components, so the React hooks cheatsheet pairs well with this page. The cheatsheet index has the rest.