@custom-variant name (selector);
@custom-variant name {
selector {
@slot;
}
}
@custom-variant name scope(document) ...;@custom-variant defines a variant. Write it at the top level of the
stylesheet.
Example
The short form takes a selector in parentheses. The block form wraps the
content with any rules, and @slot marks where the content goes.
Stylesheet
@custom-variant theme-dark (&:where([data-theme="dark"], [data-theme="dark"] *));
@custom-variant hocus {
&:hover,
&:focus-visible {
@slot;
}
}Source
import { style } from "stillwind/react";
export const link = style("theme-dark:text-white hocus:underline");Compiled code
export const link = {className:"sw_r7v8w"};Generated stylesheet without preflight
/*! stillwind v0.0.0 | MIT License | https://stillwind.dev */
/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */
@layer properties, theme, base, components, utilities;
@layer theme {
:root, :host {
--color-white: #fff;
}
}
@layer utilities {
.sw_r7v8w:where([data-theme="dark"], [data-theme="dark"] *) {
color: var(--color-white);
}
.sw_r7v8w:hover, .sw_r7v8w:focus-visible {
text-decoration-line: underline;
}
}The block form can also contain at-rules, such as @media or @supports,
around @slot.
Selectors without &
& refers to the element that the utility styles. As in CSS Nesting, a
selector without & selects descendants:
@custom-variant expanded ([aria-expanded="true"]) means
& [aria-expanded="true"].
implicit-nesting-selector
reports such a selector, and its fix writes the & without changing the
meaning.
Document-level elements
scope(document) after the name keeps selectors without & as written, so the
variant can select a document-level element such as :host or :root.
Stylesheet
@custom-variant shell scope(document) (:host);Source
import { style } from "stillwind/react";
export const css = style.css("shell:block shell:p-4 [button]:rounded-md");Compiled code
export const css = "/*! stillwind v0.0.0 | MIT License | https://stillwind.dev */\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n:where(:root, :host){--spacing:0.25rem;--radius-md:0.375rem;}:host{display:block;}:host{padding:calc(var(--spacing) * 4);}button{border-radius:var(--radius-md);}";In style.css(), the first such variant selects the element that the utility
styles. In style(), the rule stays document-wide, and
document-scoped-selector reports it.
Definitions with the same name
A later variant definition with the same name replaces the earlier one. duplicate-definition reports it. To match several selectors, list them in one definition.
The order of variant definitions decides the output order of rules with different variants. A definition in your stylesheet comes after the built-in variants.