Tailwind CSS v4
Utility classes are the default. Custom CSS is the escape hatch.
Tailwind builds on CSS fundamentals. Before writing or reviewing
Tailwind code, invoke the css skill to load specificity, box model,
and layout knowledge.
Skill(frontend:css)
Skip only for trivial class additions where no CSS reasoning is needed.
Tailwind CSS uses CSS-first configuration: design tokens live in @theme, custom utilities use @utility, and there is
no JavaScript configuration file. Constrain yourself to the design system; break out only with intention.
References
- Theme — [
${CLAUDE_SKILL_DIR}/references/theme-configuration.md]: Theme tokens, @theme options, namespace
mapping, color system
- Class authoring — [
${CLAUDE_SKILL_DIR}/references/class-authoring.md]: Class composition, variants, dark mode,
breakpoints
- Custom utilities — [
${CLAUDE_SKILL_DIR}/references/custom-utilities-and-variants.md]: @utility,
@custom-variant, directives, @source
- Layout — [
${CLAUDE_SKILL_DIR}/references/layout.md]: Display, position, flexbox, grid, alignment, order
utilities
- Sizing — [
${CLAUDE_SKILL_DIR}/references/sizing-and-spacing.md]: Spacing scale, width/height, padding/margin,
borders, box model
- Typography — [
${CLAUDE_SKILL_DIR}/references/typography.md]: Font properties, text spacing, styling, decoration,
layout
- Backgrounds — [
${CLAUDE_SKILL_DIR}/references/backgrounds-and-effects.md]: Gradients, shadows, rings, opacity,
SVG, filters
- Transforms — [
${CLAUDE_SKILL_DIR}/references/transforms-and-animations.md]: Transitions, animations, 2D/3D
transforms, masks
- Framework — [
${CLAUDE_SKILL_DIR}/references/framework-integration.md]: Preflight, CSS Modules, class binding
(React, Vue, Svelte)
Entry Point and Installation
- Single import:
@import "tailwindcss"; — provides preflight reset, theme variables, and all utilities. No
@tailwind base/components/utilities (v3 syntax)
- Vite: install
@tailwindcss/vite plugin. PostCSS: install @tailwindcss/postcss. CLI:
npx @tailwindcss/cli -i input.css -o output.css
- No
tailwind.config.js in v4 — all configuration lives in CSS via @theme
- Remove
postcss-import and autoprefixer — v4 handles both internally
- Do not use Sass, Less, or Stylus with Tailwind v4 — Tailwind is the preprocessor (handles
@import, nesting,
variables, vendor prefixes)
Theme Configuration (@theme)
Core Rules
@theme defines design tokens that generate utility classes — not equivalent to :root. Use @theme for values
needing utilities; use :root for CSS variables that only need var() access
@theme must be top-level (not nested under selectors or media queries)
- All
@theme values compile to :root { } CSS vars in output
- Only used CSS vars are emitted by default
- Semantic token names:
--color-primary, --color-surface — not --color-blue-500 or --color-gray-100
- OKLCH for custom colors:
oklch(0.72 0.11 178) — perceptually uniform, works with CSS color-mix()
@theme Options
@theme { } — Default: only emit used vars
@theme static { } — Always emit all vars
@theme inline { } — Inline var() references into utility output
Use @theme inline when a token references another variable — prevents CSS variable resolution failures in the cascade.
Namespace → Utility Mapping
--color-* → bg-*, text-*, border-*, ring-*, fill-*, stroke-*, etc.
--font-* → font-* (family)
--text-* → text-* (size)
--font-weight-* → font-* (weight)
--tracking-* → tracking-*
--leading-* → leading-*
--breakpoint-* → Responsive variants: sm:*, md:*
--container-* → Container query variants: @sm:*, and max-w-*
--spacing-* or --spacing → px-*, py-*, m-*, w-*, h-*, etc.
--radius-* → rounded-*
--shadow-* / --inset-shadow-* → shadow-* / inset-shadow-*
--blur-* → blur-*
--ease-* → ease-*
--animate-* → animate-*
Breakpoints generate variants, not utilities. Colors generate multiple utility families from a single namespace.
Extending, Replacing, Resetting
- Extend: Add new tokens alongside defaults — just declare new vars in
@theme
- Override: Redeclare a default var to change its value
- Reset namespace:
--color-*: initial removes all defaults in that namespace
- Reset everything:
--*: initial for fully custom theme
- Disable specific colors:
--color-lime-*: initial
Colors
- 22 color families x 11 steps (50-950) plus
black and white
- Every
--color-* token generates utilities across bg-*, text-*, border-*, ring-*, fill-*, stroke-*, etc.
- Opacity modifier:
bg-sky-500/50 — per-property, not whole-element
--alpha() for CSS opacity: compiles to color-mix(in oklab, ...)
- Never use
bg-opacity-* (removed in v4) — always bg-color/opacity
Sharing Themes
Put @theme in a standalone CSS file and @import it after @import "tailwindcss".
Class Authoring
Fundamental Rules
- Complete class names only. Never concatenate or interpolate —
text-red-600 yes, `text-${color}-600` never.
Tailwind scans source files as plain text
- Map dynamic values to static class string lookups
- Prettier plugin for ordering. Install
prettier-plugin-tailwindcss — do not manually sort classes
- CSS variable shorthand:
bg-(--brand-color) — parenthesis syntax auto-wraps in var(). Do not use
bg-[var(--brand)] (v3 verbose form)
- Modifiers stack left-to-right (v4):
dark:lg:hover:bg-indigo-600. v3 was right-to-left — reverse stacking order
when migrating
- Arbitrary values for one-offs only. Repeated values belong in
@theme
- Important suffix:
bg-red-500! — the ! goes at end, after all modifiers
- Conflict resolution: Last class in the generated stylesheet wins, not last in the HTML attribute. Don't rely on
attribute order — use conditional rendering
- Underscores = spaces in arbitrary values:
grid-cols-[1fr_500px_2fr]. Escape for literal underscore:
content-['hello\_world']
- Type hints for ambiguous CSS vars:
text-(length:--my-var) for font-size, text-(color:--my-var) for text color
Responsive Breakpoints (Mobile-First)
Unprefixed = all sizes. Prefix = that breakpoint and up.
sm: — 40rem (640px)
md: — 48rem (768px)
lg: — 64rem (1024px)
xl: — 80rem (1280px)
2xl: — 96rem (1536px)
Don't use sm: to mean "mobile only" — it means 640px and up
Unprefixed for mobile base, override at breakpoints
Range targeting: md:max-xl:flex (only between md and xl)
Arbitrary breakpoints: min-[900px]:grid-cols-3
Custom breakpoints: define in @theme { --breakpoint-xs: 30rem; }
Container Queries
@container on parent, @md:flex-row on children
- Named containers:
@container/main + @sm/main:flex-col
- Sizes range
@3xs (16rem) through @7xl (80rem)
- Arbitrary:
@min-[475px]:flex-row
- Customize via
--container-* in @theme
State Variants
- Pseudo-classes:
hover:, focus:, active:, visited:, focus-visible:, focus-within:, disabled:,
required:, invalid:, checked:, read-only:, indeterminate:, first:, last:, odd:, even:, empty:
- Conditional:
has-checked: (element has checked descendant), not-focus: (element is NOT focused)
- Group (style children based on parent):
group on parent, group-hover:text-white on child. Named groups:
group/item + group-hover/item:visible for nested disambiguation
- In-*: Like group but without marking the parent:
in-focus:opacity-100
- Peer (style based on preceding sibling):
peer on sibling, peer-invalid:visible on target. Named peers for
disambiguation
- has-* variant:
has-checked:bg-indigo-50, group-has-[a]:block, peer-has-checked:ring-2
Dark Mode
- Default is
prefers-color-scheme media query — dark: works without config
- Manual toggle via
@custom-variant dark (&:where(.dark, .dark *));
- Data attribute:
@custom-variant dark (&:where([data-theme=dark], [data-theme=dark] *));
- Prevent FOUC: Theme-detection script must be inline in
<head>, never in a deferred bundle
color-scheme for native UI: scheme-light dark:scheme-dark on <html> matches scrollbars and form controls to
active theme
Custom Utilities and Variants
@utility
- Custom utilities are inserted into the
utilities layer automatically and support all variants (hover:, focus:,
lg:, etc.)
- Simple:
@utility content-auto { content-visibility: auto; }
- Complex with nesting:
@utility scrollbar-hidden { &::-webkit-scrollbar { display: none; } }
- Functional (accepts argument): use wildcard
@utility tab-* with --value()
--value() resolution modes: --value(--ns-*) (theme key), --value(integer) (bare value), --value([integer])
(arbitrary value), --value("inherit") (literal)
- Multiple modes:
--value(--tab-size-*, integer, [integer])
--modifier() reads the modifier portion (text-lg/tight)
- Negative values: register separate
-utility-* form
- Prefer
@utility and @custom-variant over JS plugins for new code
@custom-variant
- Shorthand:
@custom-variant theme-midnight (&:where([data-theme="midnight"] *));
- Block form with
@slot for multiple rules or media queries
- Override built-in
dark variant for class-based toggling
Other Directives
@variant: Apply variants in custom CSS: @variant dark { background: black; }
@apply: Compose utilities into custom CSS — last resort only. Place in @layer components. Single-element
patterns only
@reference: Import theme context in Vue/Svelte <style> blocks or CSS Modules without duplicating output CSS
@plugin: Load JS plugins. CSS-native @utility/@custom-variant preferred
@layer precedence: base < components < utilities. Utilities always win
@source: Register additional scan paths, exclude paths, safelist with @source inline() using brace expansion
Build-Time Functions
--alpha(var(--color-lime-300) / 50%) → color-mix(in oklab, ...)
--spacing(4) → calc(var(--spacing) * 4) — also valid in arbitrary values
theme() is deprecated — use var(--color-red-500) instead
Content Detection (@source)
- Auto-scans all project files except
.gitignored, node_modules, binaries, CSS files, lock files
@source "../node_modules/@my-company/ui-lib" for external packages
@source not "../src/legacy" to exclude directories
@source inline("underline") for safelisting (brace expansion supported)
@source not inline(...) to explicitly exclude from generation
@import "tailwindcss" source(none) disables auto-detection entirely
@import "tailwindcss" source("../src") sets base scan path
Component Extraction
- Template components over
@apply. In React/Vue/Svelte, extract a component. In server templates, extract a
partial. @apply is the last resort
@apply only for single-element patterns — multi-element structures belong in template components
- Place
@apply-based classes in @layer components so utilities can override
- Acceptable
@apply uses: third-party library overrides, legacy HTML you don't control
Layout
Use flex for 1D flow, grid for 2D placement. gap over margin hacks.
sr-only for visually hidden, screen-reader accessible; not-sr-only to reverse. hidden removes from flow;
invisible keeps space
absolute inset-0 (fill parent), sticky top-0 z-10 (sticky header)
flex-1 (grow/shrink, ignore initial), flex-auto (respect initial), flex-none (fixed size)
- Grid:
grid-cols-<n>, col-span-<n>, col-span-full, grid-flow-dense
- Gap:
gap-<n>, gap-x-<n>, gap-y-<n> — works in both flex and grid
isolate creates a new stacking context without z-index
See ${CLAUDE_SKILL_DIR}/references/layout.md for full display, position, flexbox, grid, alignment, order, and
visibility utility catalogs.
Sizing and Spacing
--spacing drives all spacing utilities. 1 unit = 0.25rem (4px). Customize: @theme { --spacing: 4px; }.
Key Patterns
- Width/height:
w-<n>, h-<n> (spacing scale), w-<fraction> (percentage), w-full, w-screen, w-dvw, h-dvh.
size-<n> sets both
- Min/max:
min-w-*, max-w-*, min-h-*, max-h-*
- Padding:
p-* (all), px-*/py-*, ps-*/pe-* (logical)
- Margin: same prefixes plus
auto and negatives (-mt-4). mx-auto centers block elements
- Prefer
gap-* with flex/grid over space-x-<n> / space-y-<n>
Borders
- Width:
border, border-<n>, per-side (border-t, border-s/border-e)
- v4 default is
currentColor (v3 was gray-200) — always specify color
- Divide:
divide-x-<n>, divide-y-<n>, divide-{color} between children
Border Radius
v4 scale shift: rounded without suffix maps to xs size (was md in v3). Per-side, per-corner, and logical
variants (rounded-s-*, rounded-ss-*) available. See ${CLAUDE_SKILL_DIR}/references/sizing-and-spacing.md for the
full scale table.
Outlines and Box Model
outline-hidden over outline-none — preserves outlines in forced-colors mode
- Focus pattern:
focus:outline-2 focus:outline-offset-2 focus:outline-sky-500
box-border (default), box-content; overflow-auto, overflow-clip
overscroll-contain prevents scroll chaining
See ${CLAUDE_SKILL_DIR}/references/sizing-and-spacing.md for the full spacing scale, width/height keywords, container
scale, viewport units, and box model details.
Typography
Key Rules
- Family:
font-sans, font-serif, font-mono. Custom via --font-* in @theme
- Size:
text-xs through text-9xl — each sets both font-size and default line-height. Override inline:
text-sm/6, text-lg/loose
- Weight:
font-thin (100) through font-black (900)
tabular-nums for tables/pricing — composable, reset with normal-nums
- Prefer
text-start/text-end over text-left/text-right for i18n
text-balance for headings, text-pretty to prevent orphans in body text
truncate for single-line overflow; line-clamp-<n> for multi-line
- Text shadow (v4 new):
text-shadow-sm through text-shadow-lg
See ${CLAUDE_SKILL_DIR}/references/typography.md for full font properties, text spacing, styling, decoration, and text
layout utility catalogs.
Backgrounds and Effects
Key v4 Changes
- Gradient syntax:
bg-linear-to-r (not bg-gradient-to-r), bg-radial, bg-conic. Default interpolation is
oklab
- Shadow scale shifted by one step from v3.
shadow-sm in v3 = shadow-xs in v4
- Ring default: 1px currentColor (v3 was 3px blue) — use
ring-3 for thick rings
- Opacity modifier:
bg-{color}/{opacity} — never bg-opacity-*
SVG and Media
fill-current inherits parent text color — idiomatic for icon components
object-cover + explicit dimensions for images
aspect-square (1/1), aspect-video (16/9), aspect-3/2
See ${CLAUDE_SKILL_DIR}/references/backgrounds-and-effects.md for full gradient, shadow, ring, filter, backdrop, and
mask utility catalogs.
Transforms and Animations
- Use specific transitions:
transition-colors, transition-transform, transition-opacity — never
transition-all
- Compose transforms freely:
rotate-45 scale-110 translate-x-4
- Custom animations: define
--animate-* and @keyframes in @theme
- 3D transforms: parent needs
transform-3d for translate-z-*
- Backdrop blur for frosted glass:
backdrop-blur-sm bg-white/30
See ${CLAUDE_SKILL_DIR}/references/transforms-and-animations.md for full transition, animation, 2D/3D transform,
filter, and mask utility catalogs.
Motion and Accessibility
- Respect reduced motion. Gate animations with
motion-safe: or disable with motion-reduce:transition-none
sr-only / not-sr-only for screen reader accessibility
forced-color-adjust-none only for elements where forced colors destroys essential visual information — always
include sr-only text label
forced-colors: variant for styles only in forced colors mode
- Add
role="list" on unstyled lists — VoiceOver doesn't announce list-style: none elements as lists
Framework Integration
Preflight
- Extends reset: headings unstyled, lists have no bullets, images are
display: block
- v4 changes: buttons default
cursor: default, placeholder is text color at 50% opacity
- Disable by importing
tailwindcss/theme.css and tailwindcss/utilities.css individually
CSS Modules / SFC <style>
Each module is processed separately — causes slower builds and missing @theme context. Use @reference "../app.css"
in <style> blocks, or prefer CSS variables directly: background-color: var(--color-blue-500).
Class Binding
- React:
clsx for conditional composition, cva for variant APIs, cn = twMerge(clsx(...)) for className
overrides
- Vue:
:class="{ 'bg-indigo-600': primary }" or array with cn()
- Svelte 5:
class={cn("rounded-md", primary && "bg-indigo-600", className)}
Application
When writing Tailwind CSS:
- Apply all conventions silently — don't narrate rules being followed.
- Use utilities directly in markup. Reach for custom CSS only when utilities are insufficient.
- If an existing codebase contradicts a convention, follow the codebase and flag the divergence once.
When reviewing Tailwind CSS:
- Cite the specific violation and show the fix inline.
- Don't lecture — state what's wrong and how to fix it.
Integration
The CSS skill is a prerequisite — it provides specificity, box model, and layout knowledge that Tailwind abstracts but
does not replace. Framework skills handle class binding in each framework.
Utility classes are the default. When in doubt, keep configuration in @theme and styling in markup.
1---2name: tailwindcss3description: Tailwind CSS v4 utility-first discipline: CSS-first configuration, design tokens via @theme, and principled class composition. Invoke whenever task involves any interaction with Tailwind CSS — writing, reviewing, refactoring, debugging, or understanding utility classes, theme configuration, custom utilities, dark mode, or Tailwind integration with frameworks.4---56# Tailwind CSS v478**Utility classes are the default. Custom CSS is the escape hatch.**910<prerequisite>11**Tailwind builds on CSS fundamentals.** Before writing or reviewing12Tailwind code, invoke the `css` skill to load specificity, box model,13and layout knowledge.1415```16Skill(frontend:css)17```1819Skip only for trivial class additions where no CSS reasoning is needed.2021</prerequisite>2223Tailwind CSS uses CSS-first configuration: design tokens live in `@theme`, custom utilities use `@utility`, and there is24no JavaScript configuration file. Constrain yourself to the design system; break out only with intention.2526## References2728- **Theme** — [`${CLAUDE_SKILL_DIR}/references/theme-configuration.md`]: Theme tokens, `@theme` options, namespace29 mapping, color system30- **Class authoring** — [`${CLAUDE_SKILL_DIR}/references/class-authoring.md`]: Class composition, variants, dark mode,31 breakpoints32- **Custom utilities** — [`${CLAUDE_SKILL_DIR}/references/custom-utilities-and-variants.md`]: `@utility`,33 `@custom-variant`, directives, `@source`34- **Layout** — [`${CLAUDE_SKILL_DIR}/references/layout.md`]: Display, position, flexbox, grid, alignment, order35 utilities36- **Sizing** — [`${CLAUDE_SKILL_DIR}/references/sizing-and-spacing.md`]: Spacing scale, width/height, padding/margin,37 borders, box model38- **Typography** — [`${CLAUDE_SKILL_DIR}/references/typography.md`]: Font properties, text spacing, styling, decoration,39 layout40- **Backgrounds** — [`${CLAUDE_SKILL_DIR}/references/backgrounds-and-effects.md`]: Gradients, shadows, rings, opacity,41 SVG, filters42- **Transforms** — [`${CLAUDE_SKILL_DIR}/references/transforms-and-animations.md`]: Transitions, animations, 2D/3D43 transforms, masks44- **Framework** — [`${CLAUDE_SKILL_DIR}/references/framework-integration.md`]: Preflight, CSS Modules, class binding45 (React, Vue, Svelte)4647## Entry Point and Installation4849- Single import: `@import "tailwindcss";` — provides preflight reset, theme variables, and all utilities. No50 `@tailwind base/components/utilities` (v3 syntax)51- Vite: install `@tailwindcss/vite` plugin. PostCSS: install `@tailwindcss/postcss`. CLI:52 `npx @tailwindcss/cli -i input.css -o output.css`53- No `tailwind.config.js` in v4 — all configuration lives in CSS via `@theme`54- Remove `postcss-import` and `autoprefixer` — v4 handles both internally55- Do not use Sass, Less, or Stylus with Tailwind v4 — Tailwind is the preprocessor (handles `@import`, nesting,56 variables, vendor prefixes)5758## Theme Configuration (`@theme`)5960### Core Rules6162- `@theme` defines design tokens that generate utility classes — not equivalent to `:root`. Use `@theme` for values63 needing utilities; use `:root` for CSS variables that only need `var()` access64- `@theme` must be top-level (not nested under selectors or media queries)65- All `@theme` values compile to `:root { }` CSS vars in output66- Only used CSS vars are emitted by default67- Semantic token names: `--color-primary`, `--color-surface` — not `--color-blue-500` or `--color-gray-100`68- OKLCH for custom colors: `oklch(0.72 0.11 178)` — perceptually uniform, works with CSS `color-mix()`6970### `@theme` Options7172- **`@theme { }`** — Default: only emit used vars73- **`@theme static { }`** — Always emit all vars74- **`@theme inline { }`** — Inline `var()` references into utility output7576Use `@theme inline` when a token references another variable — prevents CSS variable resolution failures in the cascade.7778### Namespace → Utility Mapping7980- **`--color-*`** → `bg-*`, `text-*`, `border-*`, `ring-*`, `fill-*`, `stroke-*`, etc.81- **`--font-*`** → `font-*` (family)82- **`--text-*`** → `text-*` (size)83- **`--font-weight-*`** → `font-*` (weight)84- **`--tracking-*`** → `tracking-*`85- **`--leading-*`** → `leading-*`86- **`--breakpoint-*`** → Responsive variants: `sm:*`, `md:*`87- **`--container-*`** → Container query variants: `@sm:*`, and `max-w-*`88- **`--spacing-*` or `--spacing`** → `px-*`, `py-*`, `m-*`, `w-*`, `h-*`, etc.89- **`--radius-*`** → `rounded-*`90- **`--shadow-*` / `--inset-shadow-*`** → `shadow-*` / `inset-shadow-*`91- **`--blur-*`** → `blur-*`92- **`--ease-*`** → `ease-*`93- **`--animate-*`** → `animate-*`9495Breakpoints generate variants, not utilities. Colors generate multiple utility families from a single namespace.9697### Extending, Replacing, Resetting9899- **Extend:** Add new tokens alongside defaults — just declare new vars in `@theme`100- **Override:** Redeclare a default var to change its value101- **Reset namespace:** `--color-*: initial` removes all defaults in that namespace102- **Reset everything:** `--*: initial` for fully custom theme103- **Disable specific colors:** `--color-lime-*: initial`104105### Colors106107- 22 color families x 11 steps (50-950) plus `black` and `white`108- Every `--color-*` token generates utilities across `bg-*`, `text-*`, `border-*`, `ring-*`, `fill-*`, `stroke-*`, etc.109- Opacity modifier: `bg-sky-500/50` — per-property, not whole-element110- `--alpha()` for CSS opacity: compiles to `color-mix(in oklab, ...)`111- Never use `bg-opacity-*` (removed in v4) — always `bg-color/opacity`112113### Sharing Themes114115Put `@theme` in a standalone CSS file and `@import` it after `@import "tailwindcss"`.116117## Class Authoring118119### Fundamental Rules120121- **Complete class names only.** Never concatenate or interpolate — `text-red-600` yes, `` `text-${color}-600` `` never.122 Tailwind scans source files as plain text123- Map dynamic values to static class string lookups124- **Prettier plugin for ordering.** Install `prettier-plugin-tailwindcss` — do not manually sort classes125- **CSS variable shorthand:** `bg-(--brand-color)` — parenthesis syntax auto-wraps in `var()`. Do not use126 `bg-[var(--brand)]` (v3 verbose form)127- **Modifiers stack left-to-right** (v4): `dark:lg:hover:bg-indigo-600`. v3 was right-to-left — reverse stacking order128 when migrating129- **Arbitrary values for one-offs only.** Repeated values belong in `@theme`130- **Important suffix:** `bg-red-500!` — the `!` goes at end, after all modifiers131- **Conflict resolution:** Last class in the generated stylesheet wins, not last in the HTML attribute. Don't rely on132 attribute order — use conditional rendering133- **Underscores = spaces** in arbitrary values: `grid-cols-[1fr_500px_2fr]`. Escape for literal underscore:134 `content-['hello\_world']`135- **Type hints** for ambiguous CSS vars: `text-(length:--my-var)` for font-size, `text-(color:--my-var)` for text color136137### Responsive Breakpoints (Mobile-First)138139Unprefixed = all sizes. Prefix = that breakpoint **and up**.140141- **`sm:`** — 40rem (640px)142- **`md:`** — 48rem (768px)143- **`lg:`** — 64rem (1024px)144- **`xl:`** — 80rem (1280px)145- **`2xl:`** — 96rem (1536px)146147- Don't use `sm:` to mean "mobile only" — it means 640px and up148- Unprefixed for mobile base, override at breakpoints149- Range targeting: `md:max-xl:flex` (only between md and xl)150- Arbitrary breakpoints: `min-[900px]:grid-cols-3`151- Custom breakpoints: define in `@theme { --breakpoint-xs: 30rem; }`152153### Container Queries154155- `@container` on parent, `@md:flex-row` on children156- Named containers: `@container/main` + `@sm/main:flex-col`157- Sizes range `@3xs` (16rem) through `@7xl` (80rem)158- Arbitrary: `@min-[475px]:flex-row`159- Customize via `--container-*` in `@theme`160161### State Variants162163- **Pseudo-classes:** `hover:`, `focus:`, `active:`, `visited:`, `focus-visible:`, `focus-within:`, `disabled:`,164 `required:`, `invalid:`, `checked:`, `read-only:`, `indeterminate:`, `first:`, `last:`, `odd:`, `even:`, `empty:`165- **Conditional:** `has-checked:` (element has checked descendant), `not-focus:` (element is NOT focused)166- **Group** (style children based on parent): `group` on parent, `group-hover:text-white` on child. Named groups:167 `group/item` + `group-hover/item:visible` for nested disambiguation168- **In-\*:** Like group but without marking the parent: `in-focus:opacity-100`169- **Peer** (style based on preceding sibling): `peer` on sibling, `peer-invalid:visible` on target. Named peers for170 disambiguation171- **has-\* variant:** `has-checked:bg-indigo-50`, `group-has-[a]:block`, `peer-has-checked:ring-2`172173### Dark Mode174175- Default is `prefers-color-scheme` media query — `dark:` works without config176- Manual toggle via `@custom-variant dark (&:where(.dark, .dark *));`177- Data attribute: `@custom-variant dark (&:where([data-theme=dark], [data-theme=dark] *));`178- **Prevent FOUC:** Theme-detection script must be inline in `<head>`, never in a deferred bundle179- `color-scheme` for native UI: `scheme-light dark:scheme-dark` on `<html>` matches scrollbars and form controls to180 active theme181182## Custom Utilities and Variants183184### `@utility`185186- Custom utilities are inserted into the `utilities` layer automatically and support all variants (`hover:`, `focus:`,187 `lg:`, etc.)188- Simple: `@utility content-auto { content-visibility: auto; }`189- Complex with nesting: `@utility scrollbar-hidden { &::-webkit-scrollbar { display: none; } }`190- Functional (accepts argument): use wildcard `@utility tab-*` with `--value()`191- `--value()` resolution modes: `--value(--ns-*)` (theme key), `--value(integer)` (bare value), `--value([integer])`192 (arbitrary value), `--value("inherit")` (literal)193- Multiple modes: `--value(--tab-size-*, integer, [integer])`194- `--modifier()` reads the modifier portion (`text-lg/tight`)195- Negative values: register separate `-utility-*` form196- Prefer `@utility` and `@custom-variant` over JS plugins for new code197198### `@custom-variant`199200- Shorthand: `@custom-variant theme-midnight (&:where([data-theme="midnight"] *));`201- Block form with `@slot` for multiple rules or media queries202- Override built-in `dark` variant for class-based toggling203204### Other Directives205206- **`@variant`:** Apply variants in custom CSS: `@variant dark { background: black; }`207- **`@apply`:** Compose utilities into custom CSS — last resort only. Place in `@layer components`. Single-element208 patterns only209- **`@reference`:** Import theme context in Vue/Svelte `<style>` blocks or CSS Modules without duplicating output CSS210- **`@plugin`:** Load JS plugins. CSS-native `@utility`/`@custom-variant` preferred211- **`@layer` precedence:** `base` < `components` < `utilities`. Utilities always win212- **`@source`:** Register additional scan paths, exclude paths, safelist with `@source inline()` using brace expansion213214### Build-Time Functions215216- `--alpha(var(--color-lime-300) / 50%)` → `color-mix(in oklab, ...)`217- `--spacing(4)` → `calc(var(--spacing) * 4)` — also valid in arbitrary values218- `theme()` is deprecated — use `var(--color-red-500)` instead219220## Content Detection (`@source`)221222- Auto-scans all project files except `.gitignore`d, `node_modules`, binaries, CSS files, lock files223- `@source "../node_modules/@my-company/ui-lib"` for external packages224- `@source not "../src/legacy"` to exclude directories225- `@source inline("underline")` for safelisting (brace expansion supported)226- `@source not inline(...)` to explicitly exclude from generation227- `@import "tailwindcss" source(none)` disables auto-detection entirely228- `@import "tailwindcss" source("../src")` sets base scan path229230## Component Extraction231232- **Template components over `@apply`.** In React/Vue/Svelte, extract a component. In server templates, extract a233 partial. `@apply` is the last resort234- `@apply` only for single-element patterns — multi-element structures belong in template components235- Place `@apply`-based classes in `@layer components` so utilities can override236- Acceptable `@apply` uses: third-party library overrides, legacy HTML you don't control237238## Layout239240Use flex for 1D flow, grid for 2D placement. `gap` over margin hacks.241242- `sr-only` for visually hidden, screen-reader accessible; `not-sr-only` to reverse. `hidden` removes from flow;243 `invisible` keeps space244- `absolute inset-0` (fill parent), `sticky top-0 z-10` (sticky header)245- `flex-1` (grow/shrink, ignore initial), `flex-auto` (respect initial), `flex-none` (fixed size)246- Grid: `grid-cols-<n>`, `col-span-<n>`, `col-span-full`, `grid-flow-dense`247- Gap: `gap-<n>`, `gap-x-<n>`, `gap-y-<n>` — works in both flex and grid248- `isolate` creates a new stacking context without `z-index`249250See `${CLAUDE_SKILL_DIR}/references/layout.md` for full display, position, flexbox, grid, alignment, order, and251visibility utility catalogs.252253## Sizing and Spacing254255`--spacing` drives all spacing utilities. 1 unit = 0.25rem (4px). Customize: `@theme { --spacing: 4px; }`.256257### Key Patterns258259- Width/height: `w-<n>`, `h-<n>` (spacing scale), `w-<fraction>` (percentage), `w-full`, `w-screen`, `w-dvw`, `h-dvh`.260 `size-<n>` sets both261- Min/max: `min-w-*`, `max-w-*`, `min-h-*`, `max-h-*`262- Padding: `p-*` (all), `px-*`/`py-*`, `ps-*`/`pe-*` (logical)263- Margin: same prefixes plus `auto` and negatives (`-mt-4`). `mx-auto` centers block elements264- Prefer `gap-*` with flex/grid over `space-x-<n>` / `space-y-<n>`265266### Borders267268- Width: `border`, `border-<n>`, per-side (`border-t`, `border-s`/`border-e`)269- **v4 default is `currentColor`** (v3 was `gray-200`) — always specify color270- Divide: `divide-x-<n>`, `divide-y-<n>`, `divide-{color}` between children271272### Border Radius273274**v4 scale shift:** `rounded` without suffix maps to `xs` size (was `md` in v3). Per-side, per-corner, and logical275variants (`rounded-s-*`, `rounded-ss-*`) available. See `${CLAUDE_SKILL_DIR}/references/sizing-and-spacing.md` for the276full scale table.277278### Outlines and Box Model279280- `outline-hidden` over `outline-none` — preserves outlines in forced-colors mode281- Focus pattern: `focus:outline-2 focus:outline-offset-2 focus:outline-sky-500`282- `box-border` (default), `box-content`; `overflow-auto`, `overflow-clip`283- `overscroll-contain` prevents scroll chaining284285See `${CLAUDE_SKILL_DIR}/references/sizing-and-spacing.md` for the full spacing scale, width/height keywords, container286scale, viewport units, and box model details.287288## Typography289290### Key Rules291292- Family: `font-sans`, `font-serif`, `font-mono`. Custom via `--font-*` in `@theme`293- Size: `text-xs` through `text-9xl` — each sets both `font-size` and default `line-height`. Override inline:294 `text-sm/6`, `text-lg/loose`295- Weight: `font-thin` (100) through `font-black` (900)296- `tabular-nums` for tables/pricing — composable, reset with `normal-nums`297- Prefer `text-start`/`text-end` over `text-left`/`text-right` for i18n298- `text-balance` for headings, `text-pretty` to prevent orphans in body text299- `truncate` for single-line overflow; `line-clamp-<n>` for multi-line300- Text shadow (v4 new): `text-shadow-sm` through `text-shadow-lg`301302See `${CLAUDE_SKILL_DIR}/references/typography.md` for full font properties, text spacing, styling, decoration, and text303layout utility catalogs.304305## Backgrounds and Effects306307### Key v4 Changes308309- **Gradient syntax:** `bg-linear-to-r` (not `bg-gradient-to-r`), `bg-radial`, `bg-conic`. Default interpolation is310 **oklab**311- **Shadow scale shifted by one step from v3.** `shadow-sm` in v3 = `shadow-xs` in v4312- **Ring default:** 1px currentColor (v3 was 3px blue) — use `ring-3` for thick rings313- Opacity modifier: `bg-{color}/{opacity}` — never `bg-opacity-*`314315### SVG and Media316317- `fill-current` inherits parent text color — idiomatic for icon components318- `object-cover` + explicit dimensions for images319- `aspect-square` (1/1), `aspect-video` (16/9), `aspect-3/2`320321See `${CLAUDE_SKILL_DIR}/references/backgrounds-and-effects.md` for full gradient, shadow, ring, filter, backdrop, and322mask utility catalogs.323324## Transforms and Animations325326- Use specific transitions: `transition-colors`, `transition-transform`, `transition-opacity` — **never**327 `transition-all`328- Compose transforms freely: `rotate-45 scale-110 translate-x-4`329- Custom animations: define `--animate-*` and `@keyframes` in `@theme`330- 3D transforms: parent needs `transform-3d` for `translate-z-*`331- Backdrop blur for frosted glass: `backdrop-blur-sm bg-white/30`332333See `${CLAUDE_SKILL_DIR}/references/transforms-and-animations.md` for full transition, animation, 2D/3D transform,334filter, and mask utility catalogs.335336## Motion and Accessibility337338- **Respect reduced motion.** Gate animations with `motion-safe:` or disable with `motion-reduce:transition-none`339- `sr-only` / `not-sr-only` for screen reader accessibility340- `forced-color-adjust-none` only for elements where forced colors destroys essential visual information — always341 include `sr-only` text label342- `forced-colors:` variant for styles only in forced colors mode343- Add `role="list"` on unstyled lists — VoiceOver doesn't announce `list-style: none` elements as lists344345## Framework Integration346347### Preflight348349- Extends reset: headings unstyled, lists have no bullets, images are `display: block`350- **v4 changes:** buttons default `cursor: default`, placeholder is text color at 50% opacity351- Disable by importing `tailwindcss/theme.css` and `tailwindcss/utilities.css` individually352353### CSS Modules / SFC `<style>`354355Each module is processed separately — causes slower builds and missing `@theme` context. Use `@reference "../app.css"`356in `<style>` blocks, or prefer CSS variables directly: `background-color: var(--color-blue-500)`.357358### Class Binding359360- **React:** `clsx` for conditional composition, `cva` for variant APIs, `cn` = `twMerge(clsx(...))` for className361 overrides362- **Vue:** `:class="{ 'bg-indigo-600': primary }"` or array with `cn()`363- **Svelte 5:** `class={cn("rounded-md", primary && "bg-indigo-600", className)}`364365## Application366367When **writing** Tailwind CSS:368369- Apply all conventions silently — don't narrate rules being followed.370- Use utilities directly in markup. Reach for custom CSS only when utilities are insufficient.371- If an existing codebase contradicts a convention, follow the codebase and flag the divergence once.372373When **reviewing** Tailwind CSS:374375- Cite the specific violation and show the fix inline.376- Don't lecture — state what's wrong and how to fix it.377378## Integration379380The CSS skill is a prerequisite — it provides specificity, box model, and layout knowledge that Tailwind abstracts but381does not replace. Framework skills handle class binding in each framework.382383**Utility classes are the default. When in doubt, keep configuration in `@theme` and styling in markup.**