Theme and variants
Declare tokens, mode values, managed keyframes and reusable conditions.
Theme directives register token values and managed animations. @mode registers activation branches; @custom-variant registers utility selector and condition transformations. Their definitions become compiler input; only resources required by the resulting stylesheet are emitted, unless marked static.
@theme
Defines theme tokens and managed keyframes. Token names keep their leading --; Master CSS uses the name after -- for namespace resolution. The native rule below uses the token, so its variable is included in the result.
@theme { --color-brand: #4f46e5;}.card { background-color: var(--color-brand);}.card { background-color: var(--color-brand);}@layer theme { :root, :host { --color-brand: #4f46e5 }}@theme <mode>
Defines mode-specific token values. The final manifest must contain a matching @mode definition. Repeated token declarations merge, with later values replacing the same token; they never infer an activation selector or add color-scheme.
@mode dark { @media (prefers-color-scheme: dark) { :root, :host { @slot; } }}@theme { --color-panel: white;}@theme dark { --color-panel: #111827;}.card { background-color: var(--color-panel);}.card { background-color: var(--color-panel);}@layer theme { :root, :host { --color-panel: white } @media (prefers-color-scheme:dark) { :root { --color-panel: #111827 } } @media (prefers-color-scheme:dark) { :host { --color-panel: #111827 } }}@mode
Defines where a named mode is active, separately from its token values:
@mode ocean { [data-theme="ocean"] { @slot; }}@theme { --color-surface: white;}@theme ocean { --color-surface: #082f49;}Each branch must contain an element selector and a bare @slot;. Branches may
nest selectors, @media, and @supports. Declarations, pseudo-elements,
@container, layers, and recursive mode references are rejected. A later
same-name @mode replaces the entire activation definition and moves its
cascade position to that definition's source order.
Token declarations appear on each activation selector. An @ocean utility
matches the activation element and its descendants through a zero-specificity
:where() guard. Nested token values inherit normally. Overlapping modes follow
the cascade; there is no nearest-mode exclusion or JavaScript state machine.
Use explicit :host(...) branches in a shadow tree. Selectors do not cross native
shadow or slot boundaries. Base @theme resources target :root and :host.
@mode dark { @media (prefers-color-scheme: dark) { :root:not([data-theme]) { @slot; } } [data-theme="dark"] { @slot; }}@mode light { @media (prefers-color-scheme: light) { :root:not([data-theme]) { @slot; } } [data-theme="light"] { @slot; }}/* Native declarations explicitly control browser-provided UI. */:root { color-scheme: light dark;}[data-theme="light"] { color-scheme: light;}[data-theme="dark"] { color-scheme: dark;}The preset supplies explicit system-preference light/dark branches and base values. Override both modes for manual switching. Breakpoints, modes, and custom variants share a namespace: a cross-category duplicate is an error.
@theme inline
Defines utility shorthands that are written directly into generated declarations instead of emitting CSS custom properties. Inline tokens cannot be mode-specific. Compare this result with the variable-backed token above.
@theme inline { --color-brand: #4f46e5;}@safelist "bg-brand";@layer utilities { .bg-brand { background-color: #4f46e5 }}@theme static
Emits the token or managed keyframes as initial CSS resources instead of waiting for a matching class to use them. inline and static cannot be combined.
@theme static { --color-brand: #4f46e5; @keyframes fade-in { to { opacity: 1; } }}@layer theme { :root, :host { --color-brand: #4f46e5 }}@keyframes fade-in { to { opacity: 1 }}@custom-variant
Defines reusable utility selector transformations and conditions. Branches can combine selectors such as &:hover with native conditional wrappers around @slot. Use names as suffixes such as animation:fade-in@motion-safe. Unlike @mode, a custom variant does not define where token variables are declared.
@custom-variant motion-safe { @media (prefers-reduced-motion: no-preference) { @slot; }}.notice { @variant motion-safe { transition: opacity .2s ease; }}@media (prefers-reduced-motion:no-preference) { .notice { transition: opacity .2s }}For token authoring, see Theme Tokens. For mode behavior, see Variables and Modes. For custom variant strategy, see Conditional Queries.