Directives
Directives are the @-prefixed at-rules you write in your input CSS to compose, extend, and order Tailwind's output. This page covers @apply, @utility, @custom-variant, and @layer. @theme is covered in Theme; @plugin in Plugins; and @source in @source.
@apply
@apply inlines the declarations of existing utilities into your own selector. Use it to attach utility styles to a semantic class, including inside nested selectors and media queries.
use TailwindPHP\tw;
$css = tw::generate('<div class="btn">', '
@import "tailwindcss";
@theme { --color-brand: #3b82f6; }
.btn {
@apply px-4 py-2 rounded-lg bg-brand text-white;
}
');Variants work in an @apply list — @apply bg-blue-500 hover:bg-blue-600; expands the :hover state, and responsive prefixes such as @apply px-4 md:px-6 lg:px-8; emit the corresponding @media rules. The important modifier is honored too (@apply !flex;). Nested selectors are supported, so a rule like .card { h2 { @apply text-xl font-bold; } } applies utilities to the nested h2.
@utility
@utility registers a custom utility that participates in Tailwind's engine — it sorts into the utilities layer and accepts variants like any built-in. A static utility takes a fixed body:
@utility content-auto {
content-visibility: auto;
}Because it is a real utility, variants compose automatically (hover:content-auto, md:content-auto). The body may itself use @apply and nested selectors:
@utility btn-primary {
@apply px-4 py-2 bg-blue-500 text-white rounded;
}
@utility card {
color: red;
&:hover { color: blue; }
}A functional utility uses a -* suffix in the name and reads the matched value with --value():
@utility tab-* {
tab-size: --value(--tab-size, integer);
}--value() resolves the candidate's value — here either a --tab-size-* theme token or a bare integer — so tab-4 produces tab-size: 4.
@custom-variant
@custom-variant defines a new variant you can prefix onto any utility. The compact form names the variant and gives a selector or at-rule in parentheses.
A selector-list variant uses & for the element:
@custom-variant hocus (&:hover, &:focus);hocus:bg-blue-500 then emits both the :hover and :focus rules. An attribute form works the same way:
@custom-variant loading (&[data-loading="true"]);An at-rule variant wraps matched utilities in that at-rule:
@custom-variant tablet (@media (min-width: 600px));Custom variants stack with built-ins — sm:hocus:bg-blue-500 nests the hocus selector inside the sm media query. For more involved cases, use the block form with @slot marking where the utility's declarations are injected:
@custom-variant child {
& > * {
@slot;
}
}
@custom-variant sidebar-open {
.sidebar-open & {
@slot;
}
}@layer
@layer controls cascade order using native CSS cascade layers. A bare @layer statement declares the order of layers; later layers win regardless of selector specificity. Tailwind's canonical order is:
@layer theme, base, components, utilities;This is exactly what @import "tailwindcss" sets up internally. You can declare your own order, or split it across multiple statements (@layer reset, base; then @layer components, utilities;), and assign rules to a named layer with a block:
use TailwindPHP\tw;
$css = tw::generate('<article><h1>Title</h1></article>', '
@import "tailwindcss";
@layer base {
h1 { font-size: var(--text-2xl); }
a { color: var(--color-blue-600); text-decoration-line: underline; }
}
');Adding base styles via @layer base keeps them below components and utilities, so a utility class always overrides your element defaults. The same applies to @layer components { … } for component classes that should sit beneath utilities. Anonymous layers and layer() modifiers on @import are covered in Imports.
Next steps
Theme & Customization
Define design tokens with @theme, read them in CSS with theme() and the --theme/--spacing/--alpha functions, and inspect resolved values from PHP.
Imports & Virtual Modules
Resolve @import in your CSS — virtual modules, file imports via importPaths, custom resolvers, Preflight, and per-import modifiers.