
Tailwindcss
- 3 installs
- 19 repo stars
- Updated August 1, 2026
- xobotyi/cc-foundry
Helps with frontend development tasks during AI-assisted development.
About
tailwindcss is a Claude Code skill for frontend development. It helps solo builders move faster with AI-assisted coding.
- tailwindcss
- Frontend Development
- AI-coding skill
Tailwindcss by the numbers
- 3 all-time installs (skills.sh)
- Ranked #1,841 of 2,245 Frontend Development skills by installs in the Skillselion catalog
- Data as of Aug 2, 2026 (Skillselion catalog sync)
npx skills add https://github.com/xobotyi/cc-foundry --skill tailwindcssAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 3 |
|---|---|
| repo stars | ★ 19 |
| Last updated | August 1, 2026 |
| Repository | xobotyi/cc-foundry ↗ |
What it does
Helps with frontend development tasks during AI-assisted development.
Files
Tailwind CSS v4
Utility classes are the default. Custom CSS is the escape hatch.
<prerequisite> 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. </prerequisite>
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
| Topic | Reference | Contents |
|---|---|---|
| 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/viteplugin. PostCSS: install@tailwindcss/postcss.
CLI: npx @tailwindcss/cli -i input.css -o output.css
- No
tailwind.config.jsin v4 — all configuration lives in CSS via@theme - Remove
postcss-importandautoprefixer— 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
@themedefines 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
@thememust be top-level (not nested under selectors or media queries)- All
@themevalues 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
| Option | Behavior |
|---|---|
@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
| Namespace | Generated utilities |
|---|---|
--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-*: initialremoves all defaults in that namespace - Reset everything:
--*: initialfor fully custom theme - Disable specific colors:
--color-lime-*: initial
Colors
- 22 color families x 11 steps (50-950) plus
blackandwhite - Every
--color-*token generates utilities acrossbg-*,text-*,
border-*, ring-*, fill-*, stroke-*, etc.
- Opacity modifier:
bg-sky-500/50— per-property, not whole-element --alpha()for CSS opacity: compiles tocolor-mix(in oklab, ...)- Never use
bg-opacity-*(removed in v4) — alwaysbg-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.
| Prefix | Min-width | Prefix | Min-width |
|---|---|---|---|
sm: | 40rem (640px) | xl: | 80rem (1280px) |
md: | 48rem (768px) | 2xl: | 96rem (1536px) |
lg: | 64rem (1024px) |
- 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
@containeron parent,@md:flex-rowon 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):
groupon 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):
peeron 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-schememedia 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-schemefor native UI:scheme-light dark:scheme-darkon<html>
matches scrollbars and form controls to active theme
Custom Utilities and Variants
@utility
- Custom utilities are inserted into the
utilitieslayer 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
@utilityand@custom-variantover JS plugins for new code
@custom-variant
- Shorthand:
@custom-variant theme-midnight (&:where([data-theme="midnight"] *));
- Block form with
@slotfor multiple rules or media queries - Override built-in
darkvariant 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 valuestheme()is deprecated — usevar(--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
@applyonly for single-element patterns — multi-element structures belong
in template components
- Place
@apply-based classes in@layer componentsso utilities can override - Acceptable
@applyuses: 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-onlyfor visually hidden, screen-reader accessible;not-sr-onlyto
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 isolatecreates a new stacking context withoutz-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
autoand negatives (-mt-4).
mx-auto centers block elements
- Prefer
gap-*with flex/grid overspace-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-hiddenoveroutline-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-clipoverscroll-containprevents 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-xsthroughtext-9xl— each sets bothfont-sizeand default
line-height. Override inline: text-sm/6, text-lg/loose
- Weight:
font-thin(100) throughfont-black(900) tabular-numsfor tables/pricing — composable, reset withnormal-nums- Prefer
text-start/text-endovertext-left/text-rightfor i18n text-balancefor headings,text-prettyto prevent orphans in body texttruncatefor single-line overflow;line-clamp-<n>for multi-line- Text shadow (v4 new):
text-shadow-smthroughtext-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(notbg-gradient-to-r),bg-radial,
bg-conic. Default interpolation is oklab
- Shadow scale shifted by one step from v3.
shadow-smin v3 =
shadow-xs in v4
- Ring default: 1px currentColor (v3 was 3px blue) — use
ring-3for
thick rings
- Opacity modifier:
bg-{color}/{opacity}— neverbg-opacity-*
SVG and Media
fill-currentinherits parent text color — idiomatic for icon componentsobject-cover+ explicit dimensions for imagesaspect-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@keyframesin@theme - 3D transforms: parent needs
transform-3dfortranslate-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-onlyfor screen reader accessibilityforced-color-adjust-noneonly 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.cssand
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:
clsxfor conditional composition,cvafor variant APIs,
cn = twMerge(clsx(...)) for className overrides
- Vue:
:class="{ 'bg-indigo-600': primary }"or array withcn() - 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.
{
"sources": {
"accent-color": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/accent-color.mdx",
"adding-custom-styles": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/adding-custom-styles.mdx",
"align-content": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/align-content.mdx",
"align-items": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/align-items.mdx",
"align-self": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/align-self.mdx",
"animation": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/animation.mdx",
"appearance": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/appearance.mdx",
"aspect-ratio": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/aspect-ratio.mdx",
"backdrop-filter": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/backdrop-filter.mdx",
"backdrop-filter-blur": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/backdrop-filter-blur.mdx",
"backdrop-filter-brightness": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/backdrop-filter-brightness.mdx",
"backdrop-filter-contrast": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/backdrop-filter-contrast.mdx",
"backdrop-filter-grayscale": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/backdrop-filter-grayscale.mdx",
"backdrop-filter-hue-rotate": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/backdrop-filter-hue-rotate.mdx",
"backdrop-filter-invert": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/backdrop-filter-invert.mdx",
"backdrop-filter-opacity": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/backdrop-filter-opacity.mdx",
"backdrop-filter-saturate": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/backdrop-filter-saturate.mdx",
"backdrop-filter-sepia": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/backdrop-filter-sepia.mdx",
"backface-visibility": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/backface-visibility.mdx",
"background-attachment": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/background-attachment.mdx",
"background-blend-mode": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/background-blend-mode.mdx",
"background-clip": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/background-clip.mdx",
"background-color": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/background-color.mdx",
"background-image": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/background-image.mdx",
"background-origin": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/background-origin.mdx",
"background-position": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/background-position.mdx",
"background-repeat": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/background-repeat.mdx",
"background-size": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/background-size.mdx",
"border-collapse": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/border-collapse.mdx",
"border-color": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/border-color.mdx",
"border-radius": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/border-radius.mdx",
"border-spacing": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/border-spacing.mdx",
"border-style": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/border-style.mdx",
"border-width": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/border-width.mdx",
"box-decoration-break": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/box-decoration-break.mdx",
"box-shadow": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/box-shadow.mdx",
"box-sizing": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/box-sizing.mdx",
"break-after": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/break-after.mdx",
"break-before": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/break-before.mdx",
"break-inside": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/break-inside.mdx",
"caption-side": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/caption-side.mdx",
"caret-color": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/caret-color.mdx",
"clear": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/clear.mdx",
"color": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/color.mdx",
"color-scheme": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/color-scheme.mdx",
"colors": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/colors.mdx",
"columns": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/columns.mdx",
"compatibility": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/compatibility.mdx",
"content": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/content.mdx",
"cursor": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/cursor.mdx",
"dark-mode": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/dark-mode.mdx",
"detecting-classes-in-source-files": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/detecting-classes-in-source-files.mdx",
"display": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/display.mdx",
"editor-setup": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/editor-setup.mdx",
"field-sizing": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/field-sizing.mdx",
"fill": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/fill.mdx",
"filter": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/filter.mdx",
"filter-blur": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/filter-blur.mdx",
"filter-brightness": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/filter-brightness.mdx",
"filter-contrast": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/filter-contrast.mdx",
"filter-drop-shadow": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/filter-drop-shadow.mdx",
"filter-grayscale": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/filter-grayscale.mdx",
"filter-hue-rotate": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/filter-hue-rotate.mdx",
"filter-invert": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/filter-invert.mdx",
"filter-saturate": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/filter-saturate.mdx",
"filter-sepia": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/filter-sepia.mdx",
"flex": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/flex.mdx",
"flex-basis": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/flex-basis.mdx",
"flex-direction": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/flex-direction.mdx",
"flex-grow": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/flex-grow.mdx",
"flex-shrink": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/flex-shrink.mdx",
"flex-wrap": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/flex-wrap.mdx",
"float": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/float.mdx",
"font-family": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/font-family.mdx",
"font-size": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/font-size.mdx",
"font-smoothing": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/font-smoothing.mdx",
"font-stretch": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/font-stretch.mdx",
"font-style": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/font-style.mdx",
"font-variant-numeric": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/font-variant-numeric.mdx",
"font-weight": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/font-weight.mdx",
"forced-color-adjust": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/forced-color-adjust.mdx",
"functions-and-directives": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/functions-and-directives.mdx",
"gap": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/gap.mdx",
"grid-auto-columns": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/grid-auto-columns.mdx",
"grid-auto-flow": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/grid-auto-flow.mdx",
"grid-auto-rows": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/grid-auto-rows.mdx",
"grid-column": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/grid-column.mdx",
"grid-row": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/grid-row.mdx",
"grid-template-columns": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/grid-template-columns.mdx",
"grid-template-rows": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/grid-template-rows.mdx",
"height": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/height.mdx",
"hover-focus-and-other-states": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/hover-focus-and-other-states.mdx",
"hyphens": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/hyphens.mdx",
"isolation": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/isolation.mdx",
"justify-content": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/justify-content.mdx",
"justify-items": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/justify-items.mdx",
"justify-self": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/justify-self.mdx",
"letter-spacing": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/letter-spacing.mdx",
"line-clamp": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/line-clamp.mdx",
"line-height": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/line-height.mdx",
"list-style-image": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/list-style-image.mdx",
"list-style-position": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/list-style-position.mdx",
"list-style-type": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/list-style-type.mdx",
"margin": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/margin.mdx",
"mask-clip": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/mask-clip.mdx",
"mask-composite": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/mask-composite.mdx",
"mask-image": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/mask-image.mdx",
"mask-mode": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/mask-mode.mdx",
"mask-origin": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/mask-origin.mdx",
"mask-position": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/mask-position.mdx",
"mask-repeat": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/mask-repeat.mdx",
"mask-size": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/mask-size.mdx",
"mask-type": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/mask-type.mdx",
"max-height": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/max-height.mdx",
"max-width": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/max-width.mdx",
"min-height": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/min-height.mdx",
"min-width": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/min-width.mdx",
"mix-blend-mode": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/mix-blend-mode.mdx",
"object-fit": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/object-fit.mdx",
"object-position": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/object-position.mdx",
"opacity": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/opacity.mdx",
"order": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/order.mdx",
"outline-color": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/outline-color.mdx",
"outline-offset": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/outline-offset.mdx",
"outline-style": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/outline-style.mdx",
"outline-width": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/outline-width.mdx",
"overflow": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/overflow.mdx",
"overflow-wrap": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/overflow-wrap.mdx",
"overscroll-behavior": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/overscroll-behavior.mdx",
"padding": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/padding.mdx",
"perspective": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/perspective.mdx",
"perspective-origin": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/perspective-origin.mdx",
"place-content": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/place-content.mdx",
"place-items": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/place-items.mdx",
"place-self": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/place-self.mdx",
"pointer-events": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/pointer-events.mdx",
"position": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/position.mdx",
"preflight": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/preflight.mdx",
"resize": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/resize.mdx",
"responsive-design": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/responsive-design.mdx",
"rotate": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/rotate.mdx",
"scale": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/scale.mdx",
"scroll-behavior": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/scroll-behavior.mdx",
"scroll-margin": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/scroll-margin.mdx",
"scroll-padding": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/scroll-padding.mdx",
"scroll-snap-align": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/scroll-snap-align.mdx",
"scroll-snap-stop": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/scroll-snap-stop.mdx",
"scroll-snap-type": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/scroll-snap-type.mdx",
"skew": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/skew.mdx",
"stroke": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/stroke.mdx",
"stroke-width": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/stroke-width.mdx",
"styling-with-utility-classes": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/styling-with-utility-classes.mdx",
"table-layout": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/table-layout.mdx",
"text-align": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/text-align.mdx",
"text-decoration-color": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/text-decoration-color.mdx",
"text-decoration-line": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/text-decoration-line.mdx",
"text-decoration-style": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/text-decoration-style.mdx",
"text-decoration-thickness": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/text-decoration-thickness.mdx",
"text-indent": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/text-indent.mdx",
"text-overflow": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/text-overflow.mdx",
"text-shadow": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/text-shadow.mdx",
"text-transform": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/text-transform.mdx",
"text-underline-offset": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/text-underline-offset.mdx",
"text-wrap": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/text-wrap.mdx",
"theme": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/theme.mdx",
"top-right-bottom-left": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/top-right-bottom-left.mdx",
"touch-action": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/touch-action.mdx",
"transform": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/transform.mdx",
"transform-origin": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/transform-origin.mdx",
"transform-style": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/transform-style.mdx",
"transition-behavior": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/transition-behavior.mdx",
"transition-delay": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/transition-delay.mdx",
"transition-duration": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/transition-duration.mdx",
"transition-property": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/transition-property.mdx",
"transition-timing-function": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/transition-timing-function.mdx",
"translate": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/translate.mdx",
"upgrade-guide": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/upgrade-guide.mdx",
"user-select": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/user-select.mdx",
"vertical-align": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/vertical-align.mdx",
"visibility": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/visibility.mdx",
"white-space": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/white-space.mdx",
"width": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/width.mdx",
"will-change": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/will-change.mdx",
"word-break": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/word-break.mdx",
"z-index": "https://github.com/tailwindlabs/tailwindcss.com/raw/refs/heads/main/src/docs/z-index.mdx"
},
"lastFetched": "2026-02-18T08:47:34.783Z"
}
Backgrounds & Effects
1. Background Color
Apply theme colors with bg-{color}-{shade}. Use the / opacity modifier — never bg-opacity-*.
| Class | CSS |
|---|---|
bg-white | background-color: var(--color-white) |
bg-blue-500 | background-color: var(--color-blue-500) |
bg-transparent | background-color: transparent |
bg-inherit | background-color: inherit |
bg-current | background-color: currentColor |
bg-blue-500/50 | background-color: oklch(... / 0.5) — opacity modifier |
bg-(--my-color) | background-color: var(--my-color) — CSS variable shorthand |
bg-[#316ff6] | background-color: #316ff6 — arbitrary value |
v4 rule: bg-opacity-50 is removed. Always use bg-color/50.
---
2. Background Image & Gradients
Image
<div class="bg-[url(/img/hero.jpg)] bg-cover bg-center bg-no-repeat"></div>Remove with bg-none.
Linear Gradients — v4 syntax
bg-gradient-to-r is the v3 form. In v4 use bg-linear-*.
| Class | CSS |
|---|---|
bg-linear-to-r | linear-gradient(to right, var(--tw-gradient-stops)) |
bg-linear-to-br | linear-gradient(to bottom right, ...) |
bg-linear-45 | linear-gradient(45deg in oklab, ...) |
bg-linear-to-r/srgb | interpolate in sRGB color space |
bg-linear-to-r/oklch | interpolate in oklch (perceptually uniform hues) |
Default interpolation is oklab. Directions: t, tr, r, br, b, bl, l, tl.
Radial & Conic Gradients
| Class | Example |
|---|---|
bg-radial | center radial gradient |
bg-radial-[at_50%_75%] | positioned radial gradient |
bg-conic | conic starting at 0° |
bg-conic-180 | conic starting at 180° |
bg-conic/decreasing | decreasing hue interpolation |
Gradient Color Stops
| Class | Effect |
|---|---|
from-indigo-500 | start color |
via-purple-500 | mid color |
to-pink-500 | end color |
from-10% | start position |
via-30% | mid position |
to-90% | end position |
from-blue-500/50 | start color with opacity |
Stops support the same opacity modifier syntax as bg-*.
Gradient examples
<!-- Linear left-to-right -->
<div class="bg-linear-to-r from-cyan-500 to-blue-500"></div>
<!-- Angled with opacity -->
<div class="bg-linear-65 from-purple-500/80 to-pink-500"></div>
<!-- Radial positioned -->
<div class="bg-radial-[at_50%_75%] from-sky-200 via-blue-400 to-indigo-900 to-90%"></div>
<!-- Gradient text -->
<p class="bg-linear-to-r from-pink-500 to-violet-500 bg-clip-text text-transparent">Hello</p>---
3. Background Size, Position, Repeat, Attachment
Size
| Class | CSS |
|---|---|
bg-cover | background-size: cover |
bg-contain | background-size: contain |
bg-auto | background-size: auto |
bg-size-[auto_100px] | arbitrary size |
Position
| Class | CSS |
|---|---|
bg-center | background-position: center |
bg-top | background-position: top |
bg-bottom-right | background-position: bottom right |
bg-position-[center_top_1rem] | arbitrary position |
All 9 positions: top-left, top, top-right, left, center, right, bottom-left, bottom, bottom-right.
Repeat
| Class | CSS |
|---|---|
bg-repeat | background-repeat: repeat |
bg-repeat-x | repeat horizontally |
bg-repeat-y | repeat vertically |
bg-repeat-space | repeat without clipping |
bg-repeat-round | repeat without clipping, stretch to avoid gaps |
bg-no-repeat | no repeat |
Attachment
| Class | CSS |
|---|---|
bg-fixed | fixed relative to viewport |
bg-local | scrolls with container and viewport |
bg-scroll | scrolls with viewport, not container |
---
4. Background Clip & Origin
Clip — where background is painted
| Class | CSS |
|---|---|
bg-clip-border | background-clip: border-box |
bg-clip-padding | background-clip: padding-box |
bg-clip-content | background-clip: content-box |
bg-clip-text | background-clip: text |
Gradient text requires bg-clip-text text-transparent:
<p class="bg-linear-to-r from-pink-500 to-violet-500 bg-clip-text text-5xl font-extrabold text-transparent">
Hello world
</p>Origin — background-position reference box
| Class | CSS |
|---|---|
bg-origin-border | background-origin: border-box |
bg-origin-padding | background-origin: padding-box (default) |
bg-origin-content | background-origin: content-box |
---
5. Background Blend Mode
Blend background image with background color.
| Class | Mode |
|---|---|
bg-blend-normal | normal |
bg-blend-multiply | multiply |
bg-blend-screen | screen |
bg-blend-overlay | overlay |
bg-blend-darken | darken |
bg-blend-lighten | lighten |
bg-blend-color-dodge | color-dodge |
bg-blend-color-burn | color-burn |
bg-blend-hard-light | hard-light |
bg-blend-soft-light | soft-light |
bg-blend-difference | difference |
bg-blend-exclusion | exclusion |
bg-blend-hue / bg-blend-saturation / bg-blend-color / bg-blend-luminosity | HSL modes |
---
6. Box Shadow
v4 Scale Shift
The shadow scale shifted by one step from v3. Map old classes to new:
| v3 class | v4 class | CSS value |
|---|---|---|
shadow (1px) | shadow-2xs | 0 1px rgb(0 0 0 / 0.05) |
shadow-sm | shadow-xs | 0 1px 2px 0 rgb(0 0 0 / 0.05) |
shadow-md→ | shadow-sm | 0 1px 3px 0 / 0 1px 2px -1px |
shadow-lg→ | shadow-md / shadow-lg | larger |
| — | shadow-xl, shadow-2xl | largest |
Do not write `shadow-sm` expecting v3 behavior — it maps to v4 `shadow-xs`.
Outer shadow
<div class="shadow-md"></div>
<div class="shadow-xl/20"></div> <!-- opacity modifier -->
<button class="shadow-lg shadow-cyan-500/50"> <!-- colored shadow -->Inset shadow
| Class | CSS |
|---|---|
inset-shadow-2xs | inset 0 1px rgb(0 0 0 / 0.05) |
inset-shadow-xs | inset 0 1px 1px rgb(0 0 0 / 0.05) |
inset-shadow-sm | inset 0 2px 4px rgb(0 0 0 / 0.05) |
inset-shadow-none | remove inset shadow |
Default inset opacity is 5% — increase with /50 modifier.
Ring (solid box-shadow outline)
ring default is 1px currentColor in v4 (not 3px blue as in v3).
| Class | CSS |
|---|---|
ring | 0 0 0 1px in currentColor |
ring-2 | 0 0 0 2px |
ring-blue-500 | ring in blue-500 |
ring-blue-500/50 | ring with opacity |
inset-ring | inset 0 0 0 1px |
inset-ring-2 | inset 0 0 0 2px |
Remove: shadow-none, inset-shadow-none, ring-0, inset-ring-0.
---
7. Opacity
opacity-{0–100} — sets the entire element's opacity including children.
<button class="opacity-100">Full</button>
<button class="opacity-50">Half</button>
<button class="disabled:opacity-75">Disabled state</button>Arbitrary: opacity-[.67]. Custom property: opacity-(--my-alpha).
Use color opacity modifiers (`bg-blue-500/50`, `text-red-600/75`) for per-property opacity. Use opacity-* only when you need to affect the whole element subtree.
---
8. Mix Blend Mode
Controls how element content blends with the stacking context behind it.
| Class | Mode |
|---|---|
mix-blend-multiply | multiply |
mix-blend-screen | screen |
mix-blend-overlay | overlay |
mix-blend-darken / mix-blend-lighten | darken/lighten |
mix-blend-plus-darker / mix-blend-plus-lighter | plus modes |
| (same set as bg-blend-*) | all CSS blend modes |
Use isolate on a parent to create a new stacking context and contain blending:
<div class="isolate flex -space-x-14">
<div class="bg-yellow-500 mix-blend-multiply ..."></div>
<div class="bg-green-500 mix-blend-multiply ..."></div>
</div>---
9. Colors (Text, Accent, Caret)
Text color
<p class="text-blue-600 dark:text-sky-400"></p>
<p class="text-blue-600/75"></p> <!-- opacity modifier -->
<p class="hover:text-blue-600"></p>Pattern: text-{color}-{shade} / text-{color}-{shade}/{opacity}.
Accent color (form controls)
Overrides browser default for checkboxes, radio buttons, progress bars.
<input type="checkbox" class="accent-pink-500" />
<input type="checkbox" class="accent-purple-500/75" /> <!-- Firefox only for opacity -->Caret color (text input cursor)
<textarea class="caret-pink-500 focus:ring-pink-500"></textarea>---
10. SVG Fill & Stroke
Fill
| Class | CSS |
|---|---|
fill-blue-500 | fill: var(--color-blue-500) |
fill-current | fill: currentColor |
fill-none | fill: none |
fill-transparent | fill: transparent |
fill-current is the idiomatic pattern for icon components — SVG inherits the parent's text color automatically:
<button class="text-indigo-600 hover:text-white">
<svg class="size-5 fill-current">...</svg>
</button>Stroke
| Class | CSS |
|---|---|
stroke-cyan-500 | stroke: var(--color-cyan-500) |
stroke-current | stroke: currentColor |
stroke-none | stroke: none |
stroke-1 | stroke-width: 1 |
stroke-2 | stroke-width: 2 |
stroke-[1.5] | stroke-width: 1.5 (arbitrary) |
---
11. Interactivity
Appearance
<select class="appearance-none ...">...</select> <!-- remove native styling -->
<input class="appearance-none forced-colors:appearance-auto" /> <!-- a11y fallback -->Cursor
Common cursors:
| Class | Use |
|---|---|
cursor-pointer | clickable element |
cursor-not-allowed | disabled state |
cursor-wait / cursor-progress | loading states |
cursor-grab / cursor-grabbing | drag handles |
cursor-text | text input |
cursor-move | draggable items |
cursor-none | hide cursor |
Arbitrary: cursor-[url(hand.cur),_pointer].
Pointer Events
<div class="pointer-events-none absolute ..."> <!-- icon overlay, passes clicks through -->
<div class="pointer-events-auto ..."> <!-- restore default -->Children still receive events. Use to make decorative overlays non-interactive.
Resize
| Class | CSS |
|---|---|
resize-none | prevent resize |
resize | both directions |
resize-y | vertical only (common for textarea) |
resize-x | horizontal only |
User Select
| Class | CSS |
|---|---|
select-none | prevent text selection |
select-text | allow text selection |
select-all | select all on click |
select-auto | browser default |
Touch Action
Controls scroll/zoom on touch devices.
| Class | CSS |
|---|---|
touch-auto | browser default |
touch-none | disable all touch interactions |
touch-pan-x | horizontal pan only |
touch-pan-y | vertical pan only |
touch-pan-left / touch-pan-right | directional pan |
touch-pan-up / touch-pan-down | directional pan |
touch-pinch-zoom | pinch zoom only |
touch-manipulation | pan + pinch, no double-tap zoom |
---
12. Object Fit & Position
For replaced elements (<img>, <video>) inside a sized container.
Object Fit
| Class | Behavior |
|---|---|
object-cover | fill container, crop if needed |
object-contain | fit inside, letterbox |
object-fill | stretch to fill (distorts) |
object-scale-down | shrink to fit, never enlarge |
object-none | natural size, no scaling |
Pattern: always pair with explicit dimensions.
<img class="h-48 w-96 object-cover object-center" src="..." />Object Position
Same 9-point grid as background-position, prefixed object-*: object-top-left, object-top, object-top-right, object-left, object-center, object-right, object-bottom-left, object-bottom, object-bottom-right.
Arbitrary: object-[25%_75%].
---
13. Aspect Ratio
| Class | CSS |
|---|---|
aspect-square | 1 / 1 |
aspect-video | 16 / 9 |
aspect-auto | auto |
aspect-3/2 | 3 / 2 (arbitrary ratio shorthand) |
aspect-[4/3] | arbitrary |
<img class="aspect-3/2 w-full object-cover" src="..." />
<iframe class="aspect-video w-full" src="..."></iframe>---
14. Columns
Multi-column layout — items flow into columns automatically.
| Class | CSS |
|---|---|
columns-3 | 3 columns |
columns-xs | column width ≈ 20rem (320px), count auto |
columns-sm | column width ≈ 24rem (384px) |
columns-md | column width ≈ 28rem (448px) |
columns-auto | columns: auto |
Set gap with gap-{size} (the standard gap utilities):
<div class="columns-3 gap-8">
<img class="aspect-3/2 mb-8 object-cover" src="..." />
<img class="aspect-square mb-8 object-cover" src="..." />
</div>
<!-- Width-based, responsive -->
<div class="columns-2 gap-4 sm:columns-3 sm:gap-8">...</div>Width-based columns (columns-xs, columns-sm, ...) use --container-* tokens. Customize in @theme { --container-4xs: 14rem; }.
Class Authoring
Class Name Rules
Complete names only. Tailwind scans source files as plain text — it cannot resolve expressions.
// NEVER
const cls = `text-${color}-600` // broken: scanner sees only the template literal
const cls = "text-" + size // broken: concatenation invisible to scanner
// ALWAYS
const map = { red: "text-red-600", blue: "text-blue-600" }
const cls = map[color] // works: full class names present in sourceNo dynamic construction — even with TypeScript types. Map values to static strings.
---
Modifier Syntax
Variants prefix the utility with variant:. Stack left-to-right, each narrowing the condition.
hover:bg-sky-700 // hover state
dark:bg-gray-800 // dark mode
sm:grid-cols-3 // responsive breakpoint ≥ 40rem
dark:lg:hover:bg-indigo-600 // dark mode AND ≥ 64rem AND hoverv4 stacking order is left-to-right (v3 was right-to-left). When migrating stacked variants involving * or prose-*, reverse the order.
// v3
first:*:pt-0
// v4
*:first:pt-0---
Responsive Breakpoints
Mobile-first: unprefixed utilities apply to all sizes; prefixed apply at that breakpoint and up.
| Prefix | Min-width |
|---|---|
sm | 40rem (640px) |
md | 48rem (768px) |
lg | 64rem (1024px) |
xl | 80rem (1280px) |
2xl | 96rem (1536px) |
<!-- mobile-first: no prefix for base, prefix for larger -->
<img class="w-16 md:w-32 lg:w-48" />
<!-- DON'T use sm: to mean "mobile only" -->
<div class="sm:text-center"> <!-- only centers ≥640px, not on mobile -->
<!-- DO: unprefixed for mobile, override at breakpoints -->
<div class="text-center sm:text-left">Range targeting:
<div class="md:max-xl:flex"> <!-- only between md and xl -->
<div class="md:max-lg:flex"> <!-- only at md breakpoint -->Arbitrary breakpoints:
<div class="min-[320px]:text-center max-[600px]:bg-sky-300">Custom breakpoints via `@theme`:
@theme {
--breakpoint-xs: 30rem;
--breakpoint-*: initial; /* reset all defaults first if needed */
--breakpoint-tablet: 40rem;
}---
Container Queries
<div class="@container">
<div class="flex flex-col @md:flex-row">...</div>
</div>
<!-- Named containers for nested scenarios -->
<div class="@container/main">
<div class="flex @sm/main:flex-col">...</div>
</div>
<!-- Arbitrary container sizes -->
<div class="@container">
<div class="flex flex-col @min-[475px]:flex-row">...</div>
</div>Container query sizes: @3xs (16rem) through @7xl (80rem). Customize via --container-*.
---
Arbitrary Values
One-off values outside the design system — use sparingly. If repeated, move to @theme.
<!-- Arbitrary color -->
<button class="bg-[#316ff6]">Sign in with Facebook</button>
<!-- Arbitrary grid -->
<div class="grid grid-cols-[24rem_2.5rem_minmax(0,1fr)]">
<!-- calc() with theme values -->
<div class="max-h-[calc(100dvh-(--spacing(6)))]">
<!-- Arbitrary property (CSS variable inline) -->
<div class="[--gutter-width:1rem] lg:[--gutter-width:2rem]">CSS variable shorthand (v4):
<!-- v3 syntax — DO NOT USE in v4 -->
<div class="bg-[--brand-color]">
<!-- v4 syntax -->
<div class="bg-(--brand-color)">Arbitrary selectors (last resort):
<div class="[&>[data-active]+span]:text-blue-600">Underscores in arbitrary values represent spaces:
<div class="grid-cols-[max-content_auto]"> <!-- correct v4 -->
<div class="grid-cols-[max-content,auto]"> <!-- v3 only, broken in v4 -->---
Important Modifier
Append ! to the end of the class name (v4). Prefix ! (v3 style) is deprecated.
<!-- v4 -->
<div class="bg-red-500! flex! hover:bg-red-600/50!">
<!-- v3 (deprecated, still works but don't use) -->
<div class="!bg-red-500 !flex">Global important flag (for legacy CSS coexistence):
@import "tailwindcss" important;---
Dark Mode
Default: prefers-color-scheme media query.
<div class="bg-white dark:bg-gray-800">Manual toggle (class-based):
@custom-variant dark (&:where(.dark, .dark *));Apply color-scheme utility to match browser UI to theme:
<html class="scheme-light dark:scheme-dark">Prevent FOUC: theme-detection script must be inline in <head>, not deferred.
---
State Variants
Pseudo-classes
<!-- Common interactive states -->
hover: focus: active: visited: focus-visible: focus-within:
<!-- Form states -->
disabled: required: invalid: checked: read-only: indeterminate:
<!-- Structural -->
first: last: odd: even: nth-3: nth-last-5: only-child: empty:
<!-- Conditional -->
has-checked: <!-- element has a checked descendant -->
not-focus: <!-- element is NOT focused -->Parent/Sibling State
<!-- group: style children based on parent state -->
<a href="#" class="group">
<h3 class="group-hover:text-white">Title</h3>
<p class="group-hover:text-white">Body</p>
</a>
<!-- Named groups for nested group disambiguation -->
<li class="group/item">
<a class="group/edit group-hover/item:visible">
<span class="group-hover/edit:text-gray-700">Call</span>
</a>
</li>
<!-- in-*: like group but without marking the parent -->
<div tabindex="0">
<div class="opacity-50 in-focus:opacity-100">...</div>
</div>
<!-- peer: style elements based on preceding sibling state -->
<input type="email" class="peer" />
<p class="invisible peer-invalid:visible">Error message</p>
<!-- Named peers -->
<input class="peer/draft" type="radio" />
<input class="peer/published" type="radio" />
<span class="peer-checked/draft:block hidden">Draft saved</span>has() Variant
<!-- Style element when it has a checked descendant -->
<label class="has-checked:bg-indigo-50 has-checked:ring-indigo-200">
<input type="radio" />
Google Pay
</label>
<!-- group-has-* and peer-has-* also available -->
<div class="group">
<svg class="hidden group-has-[a]:block">...</svg>
<p>Text with <a href="#">link</a></p>
</div>---
Conflict Resolution
Last class in the generated stylesheet wins, not last in the HTML attribute. The stylesheet order is fixed by Tailwind's generation — don't rely on attribute order to resolve conflicts.
<!-- display: grid wins, not flex — even though flex comes last in attribute -->
<div class="grid flex">Use conditional rendering instead:
<div className={gridLayout ? "grid" : "flex"}>---
Dynamic Values from Runtime Sources
Use inline styles for values from DB/API. For hover states on dynamic values, set CSS variables inline and reference with utility classes:
<button
style={{ "--bg": buttonColor, "--bg-hover": buttonColorHover }}
className="bg-(--bg) hover:bg-(--bg-hover)"
>---
v3 → v4 Migration Quick Reference
| v3 | v4 |
|---|---|
@tailwind base; @tailwind utilities; | @import "tailwindcss"; |
!bg-red-500 (prefix !) | bg-red-500! (suffix !) |
bg-[--brand] | bg-(--brand) |
shadow-sm | shadow-xs |
shadow (bare) | shadow-sm |
rounded-sm | rounded-xs |
rounded (bare) | rounded-sm |
blur-sm | blur-xs |
blur (bare) | blur-sm |
outline-none | outline-hidden |
ring (3px blue) | ring-3 + ring-blue-500 |
bg-opacity-50 | bg-black/50 |
flex-shrink-* | shrink-* |
flex-grow-* | grow-* |
overflow-ellipsis | text-ellipsis |
bg-gradient-to-r | bg-linear-to-r |
theme(colors.red.500) | var(--color-red-500) |
grid-cols-[a,b] (comma=space) | grid-cols-[a_b] (underscore=space) |
Stacking: first:*:pt-0 | Stacking: *:first:pt-0 |
tailwindcss PostCSS plugin | @tailwindcss/postcss |
tailwindcss Vite | @tailwindcss/vite plugin |
npx tailwindcss CLI | npx @tailwindcss/cli |
Border/divide default color changed: v3 used gray-200; v4 uses currentColor. Always specify a color with border-* and divide-* utilities.
Gradient variant behavior: In v4, variant overrides preserve other gradient stops. Use via-none explicitly to drop a three-stop gradient back to two stops.
*`space-x/y- and divide-x/y-` selectors changed* (performance fix). Migrate to gap with flex/grid where possible.
Hover on mobile: v4 hover: only fires when primary input supports hover (@media (hover: hover)). No action needed; this is a correctness fix.
Upgrade tool: npx @tailwindcss/upgrade handles most changes automatically. Run on a separate branch and review the diff.
Custom Utilities and Variants Reference
@utility — Custom Utility Classes
Custom utilities are inserted into the utilities layer automatically. They support all variants (hover:, focus:, lg:, etc.) without extra configuration.
Simple utility
@utility content-auto {
content-visibility: auto;
}Usage: content-auto, hover:content-auto, lg:content-auto
Complex utility (with nesting)
@utility scrollbar-hidden {
&::-webkit-scrollbar {
display: none;
}
}Functional utility (accepts argument via --value())
Use @utility tab-* (wildcard) to accept a value. The --value() function resolves the argument in three modes — any combination can be used in the same rule:
@utility tab-* {
tab-size: --value(--tab-size-*); /* theme key */
tab-size: --value(integer); /* bare value */
tab-size: --value([integer]); /* arbitrary value */
}Unresolved declarations are omitted from output. Multiple --value() calls in the same @utility are tried independently.
--value() resolution modes
| Syntax | Matches | Example class |
|---|---|---|
--value(--ns-*) | Theme key in --ns-* namespace | tab-github (if --tab-size-github exists) |
--value(integer) | Bare integer | tab-4, tab-76 |
--value(number) | Bare decimal number | opacity-75 |
--value(percentage) | Bare percentage | opacity-50% |
--value(ratio) | Fraction (triggers ratio+modifier handling) | aspect-3/4 |
--value([integer]) | Arbitrary integer | tab-[8] |
--value([length]) | Arbitrary length | w-[117px] |
--value([color]) | Arbitrary color | bg-[#abc] |
--value([*]) | Any arbitrary value | |
--value("inherit", "initial") | Literal keyword | tab-inherit |
Bare value types: number, integer, ratio, percentage. Arbitrary value types: absolute-size, angle, bg-size, color, family-name, generic-name, image, integer, length, line-width, number, percentage, position, ratio, relative-size, url, vector, *.
Multiple modes in one declaration (left-to-right resolution)
@utility tab-* {
tab-size: --value(--tab-size-*, integer, [integer]);
}Modifiers via --modifier()
Works like --value() but reads the modifier portion (text-lg/tight → modifier is tight):
@utility text-* {
font-size: --value(--text-*, [length]);
line-height: --modifier(--leading-*, [length], [*]);
}If no modifier is present, modifier-dependent declarations are omitted.
Negative values
Register a separate -utility-* form:
@utility inset-* {
inset: --spacing(--value(integer));
inset: --value([percentage], [length]);
}
@utility -inset-* {
inset: --spacing(--value(integer) * -1);
inset: calc(--value([percentage], [length]) * -1);
}Fractions (ratio type)
@utility aspect-* {
aspect-ratio: --value(--aspect-ratio-*, ratio, [ratio]);
}ratio type treats value + modifier as a single fraction: aspect-3/4, aspect-[7/9].
---
@custom-variant — Custom Variants
Shorthand (single selector condition)
@custom-variant theme-midnight (&:where([data-theme="midnight"] *));
@custom-variant dark (&:where(.dark, .dark *));Usage: theme-midnight:bg-black, dark:text-white
Block form (multiple rules or media queries)
@custom-variant any-hover {
@media (any-hover: hover) {
&:hover {
@slot;
}
}
}@slot marks where the utility CSS is injected. Required in block form when nesting.
Dark mode override
Override the built-in dark variant for class-based toggling:
/* Class-based */
@custom-variant dark (&:where(.dark, .dark *));
/* Data attribute */
@custom-variant dark (&:where([data-theme=dark], [data-theme=dark] *));Default (no override): dark: uses @media (prefers-color-scheme: dark).
---
@variant — Apply Variants in Custom CSS
Use @variant inside custom CSS rules to apply a Tailwind variant:
.my-element {
background: white;
@variant dark {
background: black;
}
}Compiles to:
.my-element {
background: white;
@media (prefers-color-scheme: dark) {
background: black;
}
}Multiple variants: nest them:
.my-element {
@variant dark {
@variant hover {
background: black;
}
}
}---
@apply — Inline Utility Classes into Custom CSS
Use @apply to compose utility classes into a custom CSS rule. Last resort only — prefer template components in React/Vue/Svelte.
@layer components {
.btn-primary {
@apply rounded-lg bg-indigo-600 px-4 py-2 text-sm font-semibold text-white;
@apply hover:bg-indigo-500 focus:outline-none focus:ring-2 focus:ring-indigo-500;
}
}Rules:
- Place
@apply-based classes in@layer componentsso utilities can override them - Single-element patterns only — multi-element structures belong in template components
- Acceptable: third-party library overrides, legacy HTML you don't control
- Not acceptable: replicating component structure that belongs in framework templates
---
@reference — Import Without Duplicating CSS
Use @reference in Vue/Svelte <style> blocks or CSS Modules to access theme vars, custom utilities, and custom variants without duplicating output CSS:
<style>
@reference "../../app.css";
h1 {
@apply text-2xl font-bold text-red-500;
}
</style>When using default theme only (no custom @theme, @custom-variant, @plugin):
<style>
@reference "tailwindcss";
h1 {
@apply text-2xl font-bold;
}
</style>@reference supports subpath imports (#app.css) via package.json imports field.
---
@source — Content Detection Control
/* Register path outside auto-detection */
@source "../node_modules/@my-company/ui-lib";
/* Exclude path */
@source not "../src/legacy";
/* Force-generate specific classes (safelist) */
@source inline("underline");
@source inline("{hover:,focus:,}underline");
@source inline("{hover:,}bg-red-{50,{100..900..100},950}");
/* Explicitly exclude from generation */
@source not inline("{hover:,focus:,}bg-red-{50,{100..900..100},950}");@source inline() uses brace expansion. Use for CMS/database-driven classes that don't appear as static strings in source files.
---
@plugin — Load JavaScript Plugin
@plugin "@tailwindcss/typography";
@plugin "./local-plugin.js";@plugin accepts package name or local path. Use for legacy or third-party plugins. CSS-native @utility and @custom-variant are preferred over JS plugins for new code.
---
@layer — CSS Layer Placement
@layer base {
h1 { font-size: var(--text-2xl); }
}
@layer components {
.card {
background-color: var(--color-white);
border-radius: var(--radius-lg);
padding: --spacing(6);
box-shadow: var(--shadow-xl);
}
}Layer precedence: base < components < utilities. Utilities always win over components.
---
Build-Time Functions
--alpha() — Adjust color opacity in CSS
.element {
color: --alpha(var(--color-lime-300) / 50%);
}
/* Compiles to: color: color-mix(in oklab, var(--color-lime-300) 50%, transparent); */--spacing() — Generate spacing value from theme scale
.element {
margin: --spacing(4);
}
/* Compiles to: margin: calc(var(--spacing) * 4); */Also valid in arbitrary values: py-[calc(--spacing(4)-1px)]
theme() — deprecated
theme(colors.red.500) → use var(--color-red-500) instead.
---
Arbitrary Values and Properties
Arbitrary value
<div class="top-[117px]">...</div>
<div class="bg-[#bada55]">...</div>CSS variable shorthand (v4)
<div class="bg-(--brand-color)">...</div> <!-- v4: auto-wraps in var() -->
<div class="bg-[var(--brand)]">...</div> <!-- v3 syntax: still works but verbose -->Arbitrary property
<div class="[mask-type:luminance]">...</div>
<div class="hover:[mask-type:alpha]">...</div>Arbitrary variant
<li class="lg:[&:nth-child(-n+3)]:hover:underline">...</li>Type hints for ambiguous CSS vars
<div class="text-(length:--my-var)">...</div> <!-- font-size -->
<div class="text-(color:--my-var)">...</div> <!-- text color -->Whitespace in arbitrary values
Use underscore _ for spaces: grid-cols-[1fr_500px_2fr]. URLs preserve underscores. Escape with backslash to force underscore: content-['hello\_world'].
---
Anti-Patterns
| Don't | Do |
|---|---|
Dynamic class concat: ` bg-${color}-500 ` | Static map: { blue: "bg-blue-500" } |
@apply for multi-element component | Extract a template component |
@apply as default approach | Use markup utilities; @apply is the escape hatch |
bg-[var(--brand)] | bg-(--brand) — v4 shorthand |
@layer components without utilities override intent | Put component classes in @layer components |
@source inline() for classes visible in source | Let auto-detection handle them |
| JS plugins for new utilities | Use @utility and @custom-variant in CSS |
Framework Integration
Installation
Vite (recommended)
npm install tailwindcss @tailwindcss/vite// vite.config.ts
import { defineConfig } from "vite";
import tailwindcss from "@tailwindcss/vite";
export default defineConfig({
plugins: [tailwindcss()],
});/* src/app.css */
@import "tailwindcss";PostCSS
npm install tailwindcss @tailwindcss/postcss// postcss.config.mjs
export default {
plugins: {
"@tailwindcss/postcss": {},
// Remove postcss-import and autoprefixer — v4 handles both internally
},
};CLI
npm install @tailwindcss/cli
npx @tailwindcss/cli -i input.css -o output.cssNo tailwind.config.js in v4. Configuration lives in CSS via @theme.
---
Preflight (Base Reset)
Automatically injected when using @import "tailwindcss". Key behaviors:
| Element | Preflight behavior |
|---|---|
| All elements | margin: 0; padding: 0; box-sizing: border-box; border: 0 solid |
h1–h6 | Unstyled — same size/weight as body text |
ol, ul, menu | No bullets or numbers |
img, svg, video, etc. | display: block; vertical-align: middle |
img, video | max-width: 100%; height: auto |
[hidden] | display: none !important (except hidden="until-found") |
| Buttons | cursor: default (v4; was cursor: pointer in v3) |
| Placeholder text | Current text color at 50% opacity (v4; was gray-400 in v3) |
<dialog> | Margins reset to 0 (v4) |
Extending preflight — add to @layer base:
@layer base {
h1 { font-size: var(--text-2xl); }
h2 { font-size: var(--text-xl); }
a { color: var(--color-blue-600); text-decoration-line: underline; }
}Disabling preflight — import parts individually:
@layer theme, base, components, utilities;
@import "tailwindcss/theme.css" layer(theme);
/* omit preflight.css */
@import "tailwindcss/utilities.css" layer(utilities);When importing individually, flags go on their respective imports:
/* source detection → utilities */
@import "tailwindcss/utilities.css" layer(utilities) source(none);
/* important flag → utilities */
@import "tailwindcss/utilities.css" layer(utilities) important;
/* theme(static) → theme */
@import "tailwindcss/theme.css" layer(theme) theme(static);
/* prefix → both */
@import "tailwindcss/theme.css" layer(theme) prefix(tw);
@import "tailwindcss/utilities.css" layer(utilities) prefix(tw);Third-party conflicts — override Preflight in @layer base:
@layer base {
.google-map * { border-style: none; }
}Accessibility — unstyled lists: VoiceOver does not announce list-style: none elements as lists. Add role="list" if the content is semantically a list:
<ul role="list">
<li>One</li>
</ul>---
Prettier Plugin (Class Sorting)
npm install -D prettier prettier-plugin-tailwindcss// prettier.config.mjs
export default {
plugins: ["prettier-plugin-tailwindcss"],
};Sorts classes to canonical order automatically. Do not manually sort. The plugin works with custom Tailwind configurations and integrates with every editor that supports Prettier.
Before/after example:
<!-- before -->
<button class="text-white px-4 sm:px-8 py-2 bg-sky-700 hover:bg-sky-800">
<!-- after -->
<button class="bg-sky-700 px-4 py-2 text-white hover:bg-sky-800 sm:px-8">---
Editor Tooling
VS Code / Cursor
Install Tailwind CSS IntelliSense (bradlc.vscode-tailwindcss):
- Autocomplete for utility classes,
@themevariables, directives - Linting for CSS and markup
- Hover previews (shows generated CSS)
- Syntax highlighting for
@theme,@variant,@source
If native CSS linting flags @theme or @source as errors, disable CSS validation for the project or workspace.
Zed
Built-in Tailwind CSS support (no extension needed): autocomplete, linting, hover previews. Prettier plugin works when installed.
JetBrains (WebStorm, PhpStorm)
Built-in intelligent Tailwind completions in HTML.
---
CSS Modules, Vue/Svelte <style> Blocks
Avoid using CSS Modules or SFC <style> blocks with Tailwind. Each module is processed separately — Tailwind runs once per file, causing slower builds and missing @theme context.
If you must use <style> blocks, import global styles as reference:
<!-- Button.vue -->
<style scoped>
@reference "../app.css";
button { @apply bg-blue-500; }
</style>Or use CSS variables directly (preferred — skips Tailwind processing entirely):
<style scoped>
button { background-color: var(--color-blue-500); }
</style>Do not use Sass, Less, or Stylus with Tailwind v4. Tailwind is the preprocessor: it handles @import bundling, nesting (via Lightning CSS), variables, and vendor prefixes. Using both is redundant and incompatible.
---
React Class Binding Patterns
Conditional classes — use object map, not string concatenation:
// Static lookup — scanner sees full class names
const sizes = {
sm: "px-3 py-1.5 text-sm",
md: "px-4 py-2 text-base",
lg: "px-5 py-3 text-lg",
};
function Button({ size, children }) {
return <button className={`font-bold ${sizes[size]}`}>{children}</button>;
}clsx — conditional class composition:
import clsx from "clsx";
function Button({ primary, disabled, className, children }) {
return (
<button
className={clsx(
"rounded-md px-4 py-2 font-medium",
primary ? "bg-indigo-600 text-white" : "bg-gray-100 text-gray-900",
disabled && "opacity-50 cursor-not-allowed",
className,
)}
>
{children}
</button>
);
}cva (class-variance-authority) — variant-based component API:
import { cva } from "class-variance-authority";
const button = cva("rounded-md font-medium", {
variants: {
intent: {
primary: "bg-indigo-600 text-white hover:bg-indigo-700",
secondary: "bg-gray-100 text-gray-900 hover:bg-gray-200",
danger: "bg-red-600 text-white hover:bg-red-700",
},
size: {
sm: "px-3 py-1.5 text-sm",
md: "px-4 py-2 text-base",
lg: "px-6 py-3 text-lg",
},
},
defaultVariants: { intent: "primary", size: "md" },
});
function Button({ intent, size, className, children }) {
return <button className={button({ intent, size, className })}>{children}</button>;
}cn — merge + deduplicate (tailwind-merge + clsx):
import { clsx } from "clsx";
import { twMerge } from "tailwind-merge";
export function cn(...inputs) {
return twMerge(clsx(inputs));
}
// Allows prop overrides to win over defaults
function Card({ className, children }) {
return <div className={cn("rounded-lg bg-white p-4 shadow", className)}>{children}</div>;
}
// <Card className="bg-gray-50" /> → bg-gray-50 wins over bg-whiteUse twMerge when a component accepts a className prop that should override internal defaults. Without it, both conflicting classes appear and CSS source order determines the winner (which may not be the override).
---
Vue / Svelte Class Binding Patterns
Vue:
<template>
<!-- Object syntax -->
<button :class="{ 'bg-indigo-600': primary, 'bg-gray-100': !primary }">
<!-- Array syntax with clsx -->
<button :class="cn('rounded-md px-4 py-2', primary && 'bg-indigo-600 text-white')">
</template>Svelte 5:
<script>
import { cn } from "$lib/utils";
let { primary, class: className } = $props();
</script>
<button class={cn("rounded-md px-4 py-2", primary && "bg-indigo-600", className)}>
<slot />
</button>---
color-scheme Utilities
Controls how browser-native UI elements (date pickers, scrollbars, form controls) render.
| Class | CSS |
|---|---|
scheme-light | color-scheme: light |
scheme-dark | color-scheme: dark |
scheme-light-dark | color-scheme: light dark |
scheme-only-light | color-scheme: only light |
scheme-only-dark | color-scheme: only dark |
scheme-normal | color-scheme: normal |
Apply on <html> to match native UI to theme:
<html class="scheme-light dark:scheme-dark">For explicit dark mode enforcement (no system preference):
<html class="scheme-only-dark">---
forced-color-adjust Utilities
Controls behavior in Windows High Contrast / forced colors mode.
| Class | CSS |
|---|---|
forced-color-adjust-auto | forced-color-adjust: auto — respects forced colors |
forced-color-adjust-none | forced-color-adjust: none — opts out of forced colors |
When to use `forced-color-adjust-none`: Color swatches, custom radio/checkbox UI, or any element where enforcing forced colors would destroy essential visual information (e.g., a color picker showing color options).
<fieldset>
<legend class="sr-only">Choose a color</legend>
<div class="forced-color-adjust-none grid grid-flow-col gap-3">
<label>
<input type="radio" class="sr-only" value="White" />
<span class="sr-only">White</span>
<span class="size-6 rounded-full bg-white border border-black/10"></span>
</label>
</div>
</fieldset>Always include a sr-only text label when using forced-color-adjust-none on color UI — the visual meaning is lost in forced colors mode, so accessible text is required.
Restoring at larger breakpoints:
<!-- Custom color swatches on mobile, native select on desktop -->
<fieldset class="forced-color-adjust-none lg:forced-color-adjust-auto">
<select class="hidden lg:block">...</select>
<div class="lg:hidden"><!-- color swatches --></div>
</fieldset>Testing: Enable forced colors in DevTools (Rendering panel → Emulate CSS media feature forced-colors: active).
`forced-colors` variant — apply styles only in forced colors mode:
<div class="forced-colors:outline forced-colors:outline-2">Layout & Positioning Reference
1. Display
| Class | CSS |
|---|---|
block | display: block |
inline-block | display: inline-block |
inline | display: inline |
flex | display: flex |
inline-flex | display: inline-flex |
grid | display: grid |
inline-grid | display: inline-grid |
flow-root | display: flow-root |
contents | display: contents |
hidden | display: none |
list-item | display: list-item |
table | display: table |
inline-table | display: inline-table |
table-caption | display: table-caption |
table-cell | display: table-cell |
table-column | display: table-column |
table-column-group | display: table-column-group |
table-footer-group | display: table-footer-group |
table-header-group | display: table-header-group |
table-row-group | display: table-row-group |
table-row | display: table-row |
Accessibility:
| Class | Effect |
|---|---|
sr-only | Visually hidden, readable by screen readers |
not-sr-only | Reverses sr-only (restores visible layout) |
hidden removes from document flow. invisible keeps space but hides visually — use visibility utilities for that (see §7).
Responsive example: flex md:inline-flex
---
2. Position
| Class | CSS |
|---|---|
static | position: static |
relative | position: relative |
absolute | position: absolute |
fixed | position: fixed |
sticky | position: sticky |
static— normal flow; offsets ignored; not a positioning context for children.relative— normal flow; offsets relative to natural position; IS a positioning context.absolute— removed from flow; offsets relative to nearest non-static ancestor.fixed— relative to viewport; stays in place on scroll.sticky—relativeuntil threshold crossed, thenfixedwithin its scroll container.
Inset (top / right / bottom / left)
Prefixes: inset (all), inset-x (inline), inset-y (block), top, right, bottom, left, start (inline-start), end (inline-end).
| Suffix pattern | CSS value |
|---|---|
-<number> | calc(var(--spacing) * <number>) |
--<number> | negative spacing value |
-<fraction> | calc(<fraction> * 100%) |
-full | 100% |
-auto | auto |
-px | 1px |
-(<custom>) | var(<custom>) |
-[<value>] | <value> |
Common placement patterns:
<!-- Fill parent --> <div class="absolute inset-0">
<!-- Pin top-left --> <div class="absolute top-0 left-0">
<!-- Pin top-right --> <div class="absolute top-0 right-0">
<!-- Span top edge --> <div class="absolute inset-x-0 top-0 h-16">
<!-- Span left edge --> <div class="absolute inset-y-0 left-0 w-16">
<!-- Negative offset --> <div class="absolute -top-4 -left-4">start-* / end-* map to left/right based on text direction (LTR/RTL).
Z-Index
| Class | CSS |
|---|---|
z-<number> | z-index: <number> |
-z-<number> | z-index: calc(<number> * -1) |
z-auto | z-index: auto |
z-[<value>] | z-index: <value> |
z-(<custom>) | z-index: var(<custom>) |
Responsive example: z-10 md:z-50
---
3. Float & Clear
Float — legacy wrapping layout. Prefer flex/grid for new work.
| Class | CSS |
|---|---|
float-left | float: left |
float-right | float: right |
float-start | float: inline-start |
float-end | float: inline-end |
float-none | float: none |
Clear
| Class | CSS |
|---|---|
clear-left | clear: left |
clear-right | clear: right |
clear-both | clear: both |
clear-start | clear: inline-start |
clear-end | clear: inline-end |
clear-none | clear: none |
float-start/float-end and clear-start/clear-end are logical properties — direction-aware.
---
4. Flexbox
Container
Apply flex or inline-flex to the container, then use the flex child utilities on items.
Direction
| Class | CSS |
|---|---|
flex-row | flex-direction: row |
flex-row-reverse | flex-direction: row-reverse |
flex-col | flex-direction: column |
flex-col-reverse | flex-direction: column-reverse |
Wrap
| Class | CSS |
|---|---|
flex-nowrap | flex-wrap: nowrap |
flex-wrap | flex-wrap: wrap |
flex-wrap-reverse | flex-wrap: wrap-reverse |
Flex Items
Flex shorthand
| Class | CSS |
|---|---|
flex-1 | flex: 1 (grow/shrink, ignore initial size) |
flex-auto | flex: auto (grow/shrink, respect initial) |
flex-initial | flex: 0 auto (shrink only) |
flex-none | flex: none (fixed size) |
flex-<number> | flex: <number> |
flex-<fraction> | flex: calc(<fraction> * 100%) |
flex-[<value>] | flex: <value> |
Grow
| Class | CSS |
|---|---|
grow | flex-grow: 1 |
grow-0 | flex-grow: 0 |
grow-<number> | flex-grow: <number> |
Shrink
| Class | CSS |
|---|---|
shrink | flex-shrink: 1 |
shrink-0 | flex-shrink: 0 |
shrink-<number> | flex-shrink: <number> |
Basis (initial size of flex items)
| Class | CSS value |
|---|---|
basis-<number> | calc(var(--spacing) * <number>) |
basis-<fraction> | calc(<fraction> * 100%) |
basis-full | 100% |
basis-auto | auto |
basis-3xs…basis-7xl | container scale tokens (256px–1280px) |
basis-[<value>] | <value> |
---
5. Grid
Template
| Class | CSS |
|---|---|
grid-cols-<number> | grid-template-columns: repeat(<n>, minmax(0, 1fr)) |
grid-cols-none | grid-template-columns: none |
grid-cols-subgrid | grid-template-columns: subgrid |
grid-cols-[<value>] | grid-template-columns: <value> |
grid-rows-<number> | grid-template-rows: repeat(<n>, minmax(0, 1fr)) |
grid-rows-none | grid-template-rows: none |
grid-rows-subgrid | grid-template-rows: subgrid |
grid-rows-[<value>] | grid-template-rows: <value> |
Subgrid — child container adopts parent's tracks. Requires col-span-* or row-span-* on the subgrid element to define its span within the parent.
Auto Flow
| Class | CSS |
|---|---|
grid-flow-row | grid-auto-flow: row |
grid-flow-col | grid-auto-flow: column |
grid-flow-dense | grid-auto-flow: dense |
grid-flow-row-dense | grid-auto-flow: row dense |
grid-flow-col-dense | grid-auto-flow: column dense |
Auto Columns / Rows
| Class | CSS |
|---|---|
auto-cols-auto | grid-auto-columns: auto |
auto-cols-min | grid-auto-columns: min-content |
auto-cols-max | grid-auto-columns: max-content |
auto-cols-fr | grid-auto-columns: minmax(0, 1fr) |
auto-rows-auto | grid-auto-rows: auto |
auto-rows-min | grid-auto-rows: min-content |
auto-rows-max | grid-auto-rows: max-content |
auto-rows-fr | grid-auto-rows: minmax(0, 1fr) |
Custom: auto-cols-[minmax(0,2fr)], auto-rows-(<custom>)
Column Placement
| Class | CSS |
|---|---|
col-span-<number> | grid-column: span <n> / span <n> |
col-span-full | grid-column: 1 / -1 |
col-start-<number> | grid-column-start: <n> |
-col-start-<number> | grid-column-start: calc(<n> * -1) |
col-start-auto | grid-column-start: auto |
col-end-<number> | grid-column-end: <n> |
col-end-auto | grid-column-end: auto |
col-auto | grid-column: auto |
Row Placement
| Class | CSS |
|---|---|
row-span-<number> | grid-row: span <n> / span <n> |
row-span-full | grid-row: 1 / -1 |
row-start-<number> | grid-row-start: <n> |
row-start-auto | grid-row-start: auto |
row-end-<number> | grid-row-end: <n> |
row-end-auto | grid-row-end: auto |
row-auto | grid-row: auto |
Gap
| Class | CSS |
|---|---|
gap-<number> | gap: calc(var(--spacing) * <n>) |
gap-x-<number> | column-gap: calc(var(--spacing) * <n>) |
gap-y-<number> | row-gap: calc(var(--spacing) * <n>) |
gap-[<value>] | gap: <value> |
gap-(<custom>) | gap: var(<custom>) |
Gap applies to both flex and grid containers.
Order
| Class | CSS |
|---|---|
order-<number> | order: <number> |
-order-<number> | order: calc(<number> * -1) |
order-first | order: -9999 |
order-last | order: 9999 |
order-none | order: 0 |
order-[<value>] | order: <value> |
---
6. Alignment
Alignment utilities work across both flex and grid containers. The axis semantics differ: in flex, "main axis" = direction of flex-direction; in grid, inline axis = horizontal, block axis = vertical.
justify-content — main/inline axis of container
| Class | CSS |
|---|---|
justify-start | justify-content: flex-start |
justify-end | justify-content: flex-end |
justify-end-safe | justify-content: safe flex-end |
justify-center | justify-content: center |
justify-center-safe | justify-content: safe center |
justify-between | justify-content: space-between |
justify-around | justify-content: space-around |
justify-evenly | justify-content: space-evenly |
justify-stretch | justify-content: stretch |
justify-normal | justify-content: normal |
justify-baseline | justify-content: baseline |
align-content — cross/block axis, multi-row containers
| Class | CSS |
|---|---|
content-normal | align-content: normal |
content-start | align-content: flex-start |
content-end | align-content: flex-end |
content-center | align-content: center |
content-between | align-content: space-between |
content-around | align-content: space-around |
content-evenly | align-content: space-evenly |
content-baseline | align-content: baseline |
content-stretch | align-content: stretch |
align-items — cross axis of container (all items)
| Class | CSS |
|---|---|
items-start | align-items: flex-start |
items-end | align-items: flex-end |
items-end-safe | align-items: safe flex-end |
items-center | align-items: center |
items-center-safe | align-items: safe center |
items-baseline | align-items: baseline |
items-baseline-last | align-items: last baseline |
items-stretch | align-items: stretch |
align-self — cross axis override for individual item
| Class | CSS |
|---|---|
self-auto | align-self: auto |
self-start | align-self: flex-start |
self-end | align-self: flex-end |
self-end-safe | align-self: safe flex-end |
self-center | align-self: center |
self-center-safe | align-self: safe center |
self-stretch | align-self: stretch |
self-baseline | align-self: baseline |
self-baseline-last | align-self: last baseline |
justify-items — inline axis of grid container (all items)
| Class | CSS |
|---|---|
justify-items-start | justify-items: start |
justify-items-end | justify-items: end |
justify-items-end-safe | justify-items: safe end |
justify-items-center | justify-items: center |
justify-items-center-safe | justify-items: safe center |
justify-items-stretch | justify-items: stretch |
justify-items-normal | justify-items: normal |
justify-self — inline axis override for individual grid item
| Class | CSS |
|---|---|
justify-self-auto | justify-self: auto |
justify-self-start | justify-self: start |
justify-self-end | justify-self: end |
justify-self-end-safe | justify-self: safe end |
justify-self-center | justify-self: center |
justify-self-center-safe | justify-self: safe center |
justify-self-stretch | justify-self: stretch |
place-content — shorthand for align-content + justify-content
| Class | CSS |
|---|---|
place-content-center | place-content: center |
place-content-center-safe | place-content: safe center |
place-content-start | place-content: start |
place-content-end | place-content: end |
place-content-end-safe | place-content: safe end |
place-content-between | place-content: space-between |
place-content-around | place-content: space-around |
place-content-evenly | place-content: space-evenly |
place-content-baseline | place-content: baseline |
place-content-stretch | place-content: stretch |
Safe alignment (-safe suffix) — falls back to start alignment when content overflows the container. Prevents clipping on the hidden side.
---
7. Visibility & Isolation
Visibility
| Class | CSS | Effect |
|---|---|---|
visible | visibility: visible | Normal visibility |
invisible | visibility: hidden | Hidden but retains layout space |
collapse | visibility: collapse | Table rows/cols hidden without layout shift |
invisible vs hidden: invisible keeps the element in document flow (space preserved); hidden (display: none) removes it entirely.
collapse is designed for table rows, row groups, columns, column groups — hides without affecting column widths or row heights of other cells.
Isolation
| Class | CSS |
|---|---|
isolate | isolation: isolate |
isolation-auto | isolation: auto |
isolate creates a new stacking context without needing z-index. Use to prevent mix-blend-mode or z-index from leaking across component boundaries.
---
Common Layout Recipes
Center content in a box:
<div class="flex items-center justify-center">...</div>
<!-- or -->
<div class="grid place-content-center">...</div>Sidebar + main (fixed sidebar):
<div class="flex gap-4">
<aside class="w-64 shrink-0">...</aside>
<main class="flex-1 min-w-0">...</main>
</div>Holy grail (header, footer, sidebar, main):
<div class="grid grid-rows-[auto_1fr_auto] min-h-screen">
<header>...</header>
<div class="flex">
<aside class="w-64 shrink-0">...</aside>
<main class="flex-1">...</main>
</div>
<footer>...</footer>
</div>Sticky header:
<header class="sticky top-0 z-10">...</header>Absolute overlay (fill parent):
<div class="relative">
<div class="absolute inset-0 bg-black/50">...</div>
</div>Responsive column count:
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">...</div>Auto-fit responsive grid (arbitrary value):
<div class="grid grid-cols-[repeat(auto-fill,minmax(200px,1fr))] gap-4">...</div>---
Arbitrary Values
All layout utilities accept arbitrary values in [...] and CSS custom properties in (...):
<div class="grid-cols-[200px_1fr_200px]"> <!-- custom template -->
<div class="col-span-[3]"> <!-- arbitrary span -->
<div class="top-[calc(100vh-4rem)]"> <!-- calc expression -->
<div class="z-[999]"> <!-- arbitrary z-index -->
<div class="gap-[clamp(1rem,3vw,2rem)]"> <!-- clamp -->
<div class="inset-(--nav-height)"> <!-- CSS custom property -->Sizing & Spacing Reference
Spacing Scale
--spacing CSS variable drives all spacing utilities. 1 unit = 0.25rem (4px).
| Scale | rem | px | Scale | rem | px |
|---|---|---|---|---|---|
| 0 | 0rem | 0 | 16 | 4rem | 64 |
| px | 1px | 1 | 20 | 5rem | 80 |
| 0.5 | 0.125rem | 2 | 24 | 6rem | 96 |
| 1 | 0.25rem | 4 | 28 | 7rem | 112 |
| 1.5 | 0.375rem | 6 | 32 | 8rem | 128 |
| 2 | 0.5rem | 8 | 36 | 9rem | 144 |
| 2.5 | 0.625rem | 10 | 40 | 10rem | 160 |
| 3 | 0.75rem | 12 | 44 | 11rem | 176 |
| 3.5 | 0.875rem | 14 | 48 | 12rem | 192 |
| 4 | 1rem | 16 | 56 | 14rem | 224 |
| 5 | 1.25rem | 20 | 64 | 16rem | 256 |
| 6 | 1.5rem | 24 | 72 | 18rem | 288 |
| 7 | 1.75rem | 28 | 80 | 20rem | 320 |
| 8 | 2rem | 32 | 96 | 24rem | 384 |
| 10 | 2.5rem | 40 | |||
| 12 | 3rem | 48 |
Customize via @theme { --spacing: 4px; } or extend individual steps.
---
1. Width & Height
Width (w-*)
| Class | CSS |
|---|---|
w-<number> | width: calc(var(--spacing) * <number>) |
w-<fraction> | width: calc(<fraction> * 100%) |
w-px | width: 1px |
w-auto | width: auto |
w-full | width: 100% |
w-screen | width: 100vw |
w-dvw/lvw/svw | width: 100dvw / 100lvw / 100svw |
w-dvh/lvh/svh | width: 100dvh / 100lvh / 100svh |
w-min | width: min-content |
w-max | width: max-content |
w-fit | width: fit-content |
Container scale (maps to --container-* variables):
| Class | Value | Class | Value |
|---|---|---|---|
w-3xs | 16rem (256px) | w-3xl | 48rem (768px) |
w-2xs | 18rem (288px) | w-4xl | 56rem (896px) |
w-xs | 20rem (320px) | w-5xl | 64rem (1024px) |
w-sm | 24rem (384px) | w-6xl | 72rem (1152px) |
w-md | 28rem (448px) | w-7xl | 80rem (1280px) |
w-lg | 32rem (512px) | ||
w-xl | 36rem (576px) | ||
w-2xl | 42rem (672px) |
Fractions: w-1/2, w-1/3, w-2/3, w-1/4, w-3/4, w-1/5 … w-4/5, w-1/6, w-5/6.
Height (h-*)
| Class | CSS |
|---|---|
h-<number> | height: calc(var(--spacing) * <number>) |
h-<fraction> | height: calc(<fraction> * 100%) |
h-px | height: 1px |
h-auto | height: auto |
h-full | height: 100% |
h-screen | height: 100vh |
h-dvh/lvh/svh | height: 100dvh / 100lvh / 100svh |
h-dvw/lvw/svw | height: 100dvw / 100lvw / 100svw |
h-min | height: min-content |
h-max | height: max-content |
h-fit | height: fit-content |
h-lh | height: 1lh (line-height unit) |
No container scale for height. Fractions work: h-1/2, h-1/3, h-3/4, h-9/10, etc.
Combined size (size-*)
Sets both width and height simultaneously. Accepts all the same values as w-*: size-<number>, size-<fraction>, size-px, size-auto, size-full, size-dvw/dvh/lvw/lvh/svw/svh, size-min, size-max, size-fit.
<div class="size-16 ..."><!-- 4rem × 4rem --></div>
<div class="size-full ..."><!-- 100% × 100% --></div>Min/Max Width
min-w-* and max-w-* accept the same values as w-* (number, fraction, container scale, viewport units, min, max, fit, auto/none).
max-w-none— removes max-width constraintmin-w-auto—min-width: autocontainer— responsive breakpoint-locked max-width utility:
width: 100%;
@media (width >= 40rem) { max-width: 40rem; } /* sm */
@media (width >= 48rem) { max-width: 48rem; } /* md */
@media (width >= 64rem) { max-width: 64rem; } /* lg */
@media (width >= 80rem) { max-width: 80rem; } /* xl */
@media (width >= 96rem) { max-width: 96rem; } /* 2xl */Does not center itself — add mx-auto px-4 explicitly.
Min/Max Height
min-h-* and max-h-* accept the same values as h-*.
max-h-none— removes max-height constraintmin-h-lh,max-h-lh—1lh(line-height unit)
---
2. Padding & Margin
Padding (p-*)
| Prefix | Property |
|---|---|
p | padding (all sides) |
px | padding-inline |
py | padding-block |
ps | padding-inline-start |
pe | padding-inline-end |
pt | padding-top |
pr | padding-right |
pb | padding-bottom |
pl | padding-left |
Each prefix accepts: <number>, px, (<custom-property>), [<value>]. No auto for padding.
<div class="p-4 px-8 pt-2 ps-6 ..."></div>Margin (m-*)
| Prefix | Property |
|---|---|
m | margin (all sides) |
mx | margin-inline |
my | margin-block |
ms | margin-inline-start |
me | margin-inline-end |
mt | margin-top |
mr | margin-right |
mb | margin-bottom |
ml | margin-left |
Each prefix accepts: <number>, -<number> (negative), auto, px, -px.
Auto centering: mx-auto centers block elements horizontally.
Negative margins: prefix class name with -:
<div class="-mt-8 ..."><!-- margin-top: -2rem --></div>Logical properties (padding & margin)
ps-* / pe-* map to inline-start/end — adapts to dir="ltr" or dir="rtl" automatically. ms-* / me-* same for margin.
Space between children
| Class | Effect |
|---|---|
space-x-<n> | Margin between horizontal siblings |
space-y-<n> | Margin between vertical siblings |
space-x-reverse | Use with flex-row-reverse |
space-y-reverse | Use with flex-col-reverse |
Limitation: space-* is margin-based; prefer gap-* for grid/flex layouts that wrap.
---
3. Box Model
Box Sizing
| Class | CSS |
|---|---|
box-border | box-sizing: border-box |
box-content | box-sizing: content-box |
box-border is the default (applied via Tailwind's preflight). With box-border, padding and border are included in the declared width/height.
Box Decoration Break
Controls how background, border, padding render across line/column breaks.
| Class | CSS |
|---|---|
box-decoration-clone | box-decoration-break: clone |
box-decoration-slice | box-decoration-break: slice |
Use box-decoration-clone so gradient backgrounds repeat on each line of wrapped inline text.
---
4. Borders
Border Width
| Class | CSS |
|---|---|
border | border-width: 1px |
border-<number> | border-width: <number>px |
border-x[-<n>] | border-inline-width: 1px / <n>px |
border-y[-<n>] | border-block-width: 1px / <n>px |
border-s[-<n>] | border-inline-start-width: 1px / <n>px |
border-e[-<n>] | border-inline-end-width: 1px / <n>px |
border-t[-<n>] | border-top-width: 1px / <n>px |
border-r[-<n>] | border-right-width: 1px / <n>px |
border-b[-<n>] | border-bottom-width: 1px / <n>px |
border-l[-<n>] | border-left-width: 1px / <n>px |
Divide utilities (borders between children):
| Class | Effect |
|---|---|
divide-x[-<n>] | border-inline-end-width on all but last child |
divide-y[-<n>] | border-bottom-width on all but last child |
divide-x-reverse / divide-y-reverse | For reversed flex order |
Border Style
| Class | CSS |
|---|---|
border-solid | border-style: solid |
border-dashed | border-style: dashed |
border-dotted | border-style: dotted |
border-double | border-style: double |
border-hidden | border-style: hidden |
border-none | border-style: none |
Same values available as divide-solid, divide-dashed, etc. for child dividers.
Border Color
Pattern: border-{color}-{shade} (e.g., border-indigo-500).
Special values: border-inherit, border-current, border-transparent.
Per-side: border-t-{color}, border-r-{color}, border-b-{color}, border-l-{color}, border-x-{color}, border-y-{color}, border-s-{color}, border-e-{color}.
Opacity modifier: border-indigo-500/50 sets alpha to 50%.
Divide color: divide-{color}-{shade} — same pattern.
Custom: border-[#243c5a] or border-(--my-color).
Border Radius
v4 scale shift: rounded without suffix maps to the xs size. Use explicit suffixes.
| Suffix | Value | px |
|---|---|---|
-xs | --radius-xs | 2 |
-sm | --radius-sm | 4 |
-md | --radius-md | 6 |
-lg | --radius-lg | 8 |
-xl | --radius-xl | 12 |
-2xl | --radius-2xl | 16 |
-3xl | --radius-3xl | 24 |
-4xl | --radius-4xl | 32 |
-none | 0 | 0 |
-full | calc(infinity * 1px) | pill |
Per-side (two corners): rounded-t-*, rounded-r-*, rounded-b-*, rounded-l-*.
Per-corner (physical): rounded-tl-*, rounded-tr-*, rounded-br-*, rounded-bl-*.
Logical variants:
| Class | LTR equivalent | RTL equivalent |
|---|---|---|
rounded-s-* | rounded-l-* | rounded-r-* |
rounded-e-* | rounded-r-* | rounded-l-* |
rounded-ss-* | rounded-tl-* | rounded-tr-* |
rounded-se-* | rounded-tr-* | rounded-tl-* |
rounded-es-* | rounded-bl-* | rounded-br-* |
rounded-ee-* | rounded-br-* | rounded-bl-* |
Pill button: rounded-full. Remove radius: rounded-none.
Customize: @theme { --radius-5xl: 3rem; }.
---
5. Outlines
Outlines sit outside the border, do not affect layout, and are commonly used for focus rings.
Outline Width
| Class | CSS |
|---|---|
outline | outline-width: 1px |
outline-<number> | outline-width: <number>px |
Arbitrary: outline-[2vw] or outline-(length:--my-var).
Outline Style
| Class | CSS / Effect |
|---|---|
outline-solid | outline-style: solid |
outline-dashed | outline-style: dashed |
outline-dotted | outline-style: dotted |
outline-double | outline-style: double |
outline-none | outline-style: none — completely removes outline |
outline-hidden | outline: 2px solid transparent; outline-offset: 2px |
v4 change: outline-none in v3 is now outline-hidden in v4. outline-hidden preserves the outline in forced-colors mode (accessibility). Prefer it over outline-none when hiding focus outlines; always provide alternative focus styling.
Outline Color
Pattern: outline-{color}-{shade} (e.g., outline-blue-500).
Special: outline-inherit, outline-current, outline-transparent.
Opacity: outline-blue-500/75.
Custom: outline-[#243c5a] or outline-(--my-color).
Outline Offset
| Class | CSS |
|---|---|
outline-offset-<n> | outline-offset: <n>px |
-outline-offset-<n> | outline-offset: calc(<n>px * -1) |
Common focus pattern:
<button class="focus:outline-2 focus:outline-offset-2 focus:outline-sky-500 ...">---
6. Border Spacing & Collapse (Tables)
Border Collapse
| Class | CSS |
|---|---|
border-collapse | border-collapse: collapse |
border-separate | border-collapse: separate |
border-collapse merges adjacent cell borders. border-separate keeps them distinct (required for border-spacing).
Border Spacing
Only effective with border-separate.
| Class | CSS |
|---|---|
border-spacing-<n> | border-spacing: calc(var(--spacing) * <n>) |
border-spacing-x-<n> | horizontal spacing only |
border-spacing-y-<n> | vertical spacing only |
<table class="border-separate border-spacing-2 ...">---
7. Overflow
Overflow
| Class | CSS |
|---|---|
overflow-auto | overflow: auto |
overflow-hidden | overflow: hidden |
overflow-clip | overflow: clip |
overflow-visible | overflow: visible |
overflow-scroll | overflow: scroll |
Per-axis: overflow-x-* and overflow-y-* accept the same values.
overflow-auto— adds scrollbars only when content overflowsoverflow-scroll— always shows scrollbars (OS may hide if not needed)overflow-clip— clips without creating a scroll container (unlikeoverflow-hidden)
Overscroll Behavior
Controls what happens when a scroll boundary is reached.
| Class | CSS |
|---|---|
overscroll-auto | overscroll-behavior: auto |
overscroll-contain | overscroll-behavior: contain |
overscroll-none | overscroll-behavior: none |
Per-axis: overscroll-x-* and overscroll-y-*.
overscroll-contain— prevents scroll chaining to parent; preserves bounce effectsoverscroll-none— prevents scroll chaining and bounce effectsoverscroll-auto— default; allows scroll chaining to parent
---
Value Syntax Reference
| Pattern | Example | Notes |
|---|---|---|
w-<number> | w-4, w-0.5 | Multiplied by --spacing (0.25rem) |
w-<fraction> | w-1/2, w-2/3 | Percentage of parent |
w-[<value>] | w-[220px], w-[5vw] | Arbitrary value |
w-(<custom-property>) | w-(--my-width) | CSS variable shorthand (v4) |
-m-<number> | -mt-4, -mx-8 | Negative margin |
border-(length:--var) | border-(length:--bw) | Length-typed custom property |
Theme Configuration Reference
Entry Point
@import "tailwindcss";This imports theme.css (default tokens), preflight.css (base reset), and utilities.css. No @tailwind base/components/utilities — those are v3 syntax.
---
@theme Directive
@theme defines design tokens that generate utility classes. It is not equivalent to :root.
| Placement | Generates utility classes | Use for |
|---|---|---|
@theme { ... } | Yes | Design tokens that need utility classes |
:root { ... } | No | CSS vars that don't need utilities |
Rules:
- Must be top-level (not nested under selectors or media queries)
- All values compile to
:root { ... }CSS vars in output - Only used CSS vars are emitted by default (use
staticoption to force all)
@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:
/* Without inline: font-sans may resolve incorrectly in some cascade positions */
@theme inline {
--font-sans: var(--font-inter);
}---
Namespaces → Utility Classes
| Namespace | Generated utilities |
|---|---|
--color-* | bg-*, text-*, border-*, ring-*, fill-*, stroke-*, etc. |
--font-* | font-* (font-family) |
--text-* | text-* (font-size) |
--font-weight-* | font-* (font-weight) |
--tracking-* | tracking-* (letter-spacing) |
--leading-* | leading-* (line-height) |
--breakpoint-* | Responsive variants: sm:*, md:*, etc. |
--container-* | Container query variants: @sm:*, and max-w-* |
--spacing-* or --spacing | px-*, py-*, m-*, w-*, h-*, etc. |
--radius-* | rounded-* |
--shadow-* | shadow-* |
--inset-shadow-* | inset-shadow-* |
--drop-shadow-* | drop-shadow-* |
--blur-* | blur-* |
--perspective-* | perspective-* |
--aspect-* | aspect-* |
--ease-* | ease-* |
--animate-* | animate-* |
Breakpoints generate variants, not utilities. Colors generate multiple utility families (bg-*, text-*, border-*, etc.) from a single namespace.
---
Extending vs. Replacing vs. Resetting
Extend (add new tokens alongside defaults)
@theme {
--font-script: "Great Vibes", cursive;
--breakpoint-3xl: 120rem;
--color-mint-500: oklch(0.72 0.11 178);
}Override (replace a single default value)
@theme {
--breakpoint-sm: 30rem; /* was 40rem */
}Reset a namespace (remove all defaults in that namespace, add custom)
@theme {
--color-*: initial;
--color-white: #fff;
--color-brand: oklch(0.65 0.22 260);
--color-surface: oklch(0.98 0 0);
}--color-*: initial removes ALL default color utilities. Only your custom values remain.
Reset everything (fully custom theme)
@theme {
--*: initial;
--spacing: 4px;
--font-body: Inter, sans-serif;
--color-primary: oklch(0.65 0.22 260);
}---
Colors
OKLCH format (v4 default)
All v4 default colors use OKLCH. Use OKLCH for custom colors — perceptually uniform, works reliably in CSS color-mix().
oklch(lightness chroma hue)
oklch(0.72 0.11 178) /* lightness: 0–1, chroma: 0–0.4+, hue: 0–360 */Shorthand: oklch(72% 0.11 178) also valid. Default theme uses decimal form.
Default palette
22 color families × 11 steps (50–950): red, orange, amber, yellow, lime, green, emerald, teal, cyan, sky, blue, indigo, violet, purple, fuchsia, pink, rose, slate, gray, zinc, neutral, stone. Plus black and white.
Color utilities
Every --color-* token generates utilities across: bg-*, text-*, decoration-*, border-*, outline-*, shadow-*, inset-shadow-*, ring-*, inset-ring-*, accent-*, caret-*, fill-*, stroke-*.
Opacity modifier
<div class="bg-sky-500/50">...</div> <!-- 50% opacity -->
<div class="bg-sky-500/[71.37%]">...</div> <!-- arbitrary opacity -->
<div class="bg-cyan-400/(--my-alpha)">...</div> <!-- CSS var opacity -->Referencing colors in CSS
color: var(--color-blue-500);
background-color: --alpha(var(--color-gray-950) / 10%);--alpha() compiles to color-mix(in oklab, ...). Use it over rgba() for theme colors.
Custom palette patterns
/* Add custom colors */
@theme {
--color-brand: oklch(0.65 0.22 260);
--color-surface: oklch(0.98 0 0);
}
/* Replace entire palette */
@theme {
--color-*: initial;
--color-white: #fff;
--color-brand: oklch(0.65 0.22 260);
}
/* Disable specific colors */
@theme {
--color-lime-*: initial;
--color-fuchsia-*: initial;
}
/* Reference another variable (use inline to avoid cascade issues) */
@theme inline {
--color-canvas: var(--acme-canvas-color);
}Semantic token naming
Use semantic names for design system tokens — not palette references:
/* Correct */
@theme {
--color-primary: oklch(0.51 0.26 277);
--color-surface: oklch(0.98 0 0);
--color-error: oklch(0.58 0.24 27);
}
/* Wrong — palette references as design tokens */
@theme {
--color-blue-brand: oklch(0.51 0.26 277);
}---
Dark Mode
Default: prefers-color-scheme media query
<div class="bg-white dark:bg-gray-900">...</div>No configuration needed. dark: variant uses @media (prefers-color-scheme: dark).
Manual toggle: class-based
Override the dark variant with @custom-variant:
@import "tailwindcss";
@custom-variant dark (&:where(.dark, .dark *));Now dark: utilities apply when .dark class is present on any ancestor:
<html class="dark">
<div class="bg-white dark:bg-gray-900">...</div>
</html>Manual toggle: data attribute
@custom-variant dark (&:where([data-theme=dark], [data-theme=dark] *));<html data-theme="dark">...</html>Three-way toggle (system / light / dark)
Requires inline <head> script to prevent FOUC — never in a deferred bundle:
// Must be inline in <head>
document.documentElement.classList.toggle(
"dark",
localStorage.theme === "dark" ||
(!("theme" in localStorage) && window.matchMedia("(prefers-color-scheme: dark)").matches)
);FOUC rule: Theme detection must run before paint. Deferred JS causes flash of wrong theme.
---
Content Detection (@source)
Tailwind auto-scans all project files except: .gitignored files, node_modules, binary files, CSS files, and lock files.
Register additional sources
@source "../node_modules/@my-company/ui-lib";
@source "../packages/shared-components";Required for: npm packages with Tailwind classes, monorepo packages outside auto-detection.
Set base path
@import "tailwindcss" source("../src");Useful in monorepos where build commands run from repo root.
Exclude paths
@source not "../src/components/legacy";Reduces scan scope. Use for large directories that don't use Tailwind.
Disable auto-detection
@import "tailwindcss" source(none);
@source "../admin";
@source "../shared";Safelist (force generation)
@source inline("underline");
@source inline("{hover:,focus:,}underline");
@source inline("{hover:,}bg-red-{50,{100..900..100},950}");@source inline() uses brace expansion. Use for: CMS content, database-driven classes, classes that exist only at runtime.
Explicitly exclude from generation
@source not inline("{hover:,focus:,}bg-red-{50,{100..900..100},950}");---
Sharing Theme Across Projects
Put @theme in a standalone CSS file and import it:
/* packages/brand/theme.css */
@theme {
--*: initial;
--color-brand: oklch(0.65 0.22 260);
}
/* app/app.css */
@import "tailwindcss";
@import "../packages/brand/theme.css";---
Referencing Theme Vars in JavaScript
// CSS vars work directly in JS APIs
motion.div animate={{ backgroundColor: "var(--color-blue-500)" }}
// Resolved value (rarely needed)
const val = getComputedStyle(document.documentElement).getPropertyValue("--shadow-xl");---
V3 → V4 Migration Gotchas
| V3 | V4 |
|---|---|
tailwind.config.js theme | @theme { ... } in CSS |
theme.extend.colors.brand | --color-brand: oklch(...) in @theme |
theme(colors.red.500) | var(--color-red-500) |
bg-opacity-50 | bg-black/50 (opacity modifier) |
bg-gradient-to-r | bg-linear-to-r |
shadow-sm (v3 small) | shadow-xs (scale shifted) |
rounded (v3 small) | rounded-sm (scale shifted) |
!bg-red-500 (important prefix) | bg-red-500! (important suffix) |
ring (3px blue) | ring-3 (v4 default is 1px currentColor) |
outline-none | outline-hidden |
bg-[var(--brand)] | bg-(--brand) (v4 CSS var shorthand) |
safelist in config | @source inline("class-name") |
`@config` directive: Use only for incremental v3→v4 migration. corePlugins, safelist, and separator from JS config are not supported in v4.