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.