Capítulo 1 de 29

Chapter 1: Adding Custom Styles

Core Idea

Tailwind is designed to be extended rather than escaped: customize the design tokens with @theme, break out of the token scale with arbitrary values/properties/variants using square-bracket notation, and register brand-new utilities/variants with @utility and @custom-variant instead of hand-writing parallel CSS.

Key Concepts

  • @theme directive: define custom design tokens (colors, fonts, breakpoints, easing curves) as CSS custom properties inside @theme { } in your CSS entry file; these become first-class theme values usable by every utility.
  • Arbitrary values: square-bracket notation (top-[117px], bg-[#bada55], text-[22px]) generates a one-off utility on the fly; combines with responsive/state modifiers (lg:top-[344px]).
  • Arbitrary properties: [mask-type:luminance] writes a raw CSS declaration as a class when no built-in utility exists for that property; also combines with modifiers (hover:[mask-type:alpha]).
  • Arbitrary variants: [&:nth-child(-n+3)]:hover:underline applies on-the-fly selector modification the same way hover:/md: do, but for selectors Tailwind doesn't ship a named variant for.
  • CSS variable shorthand: fill-(--my-brand-color) is shorthand for fill-[var(--my-brand-color)].
  • Whitespace in arbitrary values: use _ instead of a literal space (grid-cols-[1fr_500px_2fr]); Tailwind converts underscores to spaces at build time except where an underscore is semantically valid (URLs) or explicitly escaped (\_).
  • Type hinting for ambiguous values: text-(length:--my-var) vs text-(color:--my-var) disambiguates a shared namespace (text- maps to both font-size and color) when a CSS variable's type can't be inferred.
  • @layer base/components: @layer base holds custom default element styles (e.g. h1 { font-size: ... }); @layer components holds reusable classes like .card/.btn that stay overridable by utility classes applied after them in the cascade.
  • @variant: apply a built-in Tailwind variant inside hand-written CSS (@variant dark { ... }), including stacking (@variant hover:focus) and OR-ing (@variant hover, focus).
  • @utility: registers a new utility class, inserted into the utilities layer alongside built-ins, so it also gets variant support (hover:content-auto) for free. Complex utilities use nesting (&::-webkit-scrollbar).
  • Functional utilities (@utility tab-*): accept a dynamic value via --value(), which can resolve against theme keys (--value(--tab-size-*)), bare types (--value(integer)), literal strings (--value("inherit")), or arbitrary values (--value([integer])) — and combine several forms in one rule; unresolved declarations are silently dropped from output.
  • --modifier(): same resolution mechanism as --value() but for the /modifier slash suffix (e.g. text-* font-size with a /leading-* modifier).
  • --default(): supplies a fallback inside --value()/--modifier() so the utility works with no explicit value (tab alone resolves like tab-4).
  • Negative values: registered as a separate -utility-* rule (e.g. -inset-*), not inferred automatically.
  • @custom-variant: defines an entirely new variant (theme-midnight:bg-black) via a selector/media-query rule with @slot marking where the utility's declarations are injected; supports a shorthand one-line form and nested multi-rule variants.

Code Examples

@theme {
  --color-avocado-500: oklch(0.84 0.18 117.33);
}

@utility tab-* {
  tab-size: --value(--tab-size-*, integer, [integer]);
}

@custom-variant theme-midnight (&:where([data-theme="midnight"] *));
  • What it demonstrates: theme token definition, a functional utility resolving theme/bare/arbitrary values in one rule, and a one-line custom variant.

Reference Tables

MechanismDirectiveUse for
Design tokens@themeNew color/font/breakpoint/etc. values
One-off valuevalue-[...]A single property, no reusable utility needed
One-off property[prop:value]A CSS property with no Tailwind utility
One-off selector[&:selector]:utilA selector no built-in variant covers
Reusable utility@utilityA new named, variant-aware class
Reusable variant@custom-variantA new named modifier prefix

Key Takeaways

  1. Reach for @theme first when a new design token should be reusable; reach for arbitrary value/property/variant syntax only for genuine one-offs.
  2. @utility and @custom-variant are how you extend Tailwind itself without a plugin system or config file — both live entirely in CSS.
  3. --value()/--modifier() can chain theme → bare → arbitrary resolution in the same rule; only the first form that resolves for a given class wins, the rest are dropped silently.
  4. Negative-value utilities must be declared as their own -utility-* rule; Tailwind won't auto-negate a positive one.

Connects To

  • Theme (ch: theme): @theme tokens defined here are the same system documented in full there (namespaces, generated CSS variables, overriding vs extending).
  • Hover, Focus & Other States: @variant/@custom-variant are the CSS-side counterpart to the HTML-side modifier system covered there.
  • Detecting Classes in Source Files: arbitrary values only work because Tailwind's scanner treats source as plain text — dynamically concatenated class strings won't be detected (see that chapter's TipBad/TipGood guidance).