# Stillwind
> Compile component styles, enforce your design system, and ship static CSS.
Index: https://stillwind.dev/llms.txt
# Getting started
> Add Stillwind to a Vite and React application, style a component, and check your styles.
Source: https://stillwind.dev/docs · Markdown: https://stillwind.dev/docs/index.md
This guide adds Stillwind to a Vite application that uses React. At the end, a
button uses Stillwind styles, and the CLI checks them. For another framework or
build tool, follow the same steps and use the build setup from
[Framework integrations](/docs/integrations). To let a coding agent do the
setup, see [Coding agents](/docs/agents).
> **Early development**
>
> Stillwind is in early development. Test your application's build and pages before you release
> changes.
## Install the packages
```sh
vp i stillwind
vp i -D @stillwind/integration @stillwind/cli
```
`stillwind` provides the style API. `@stillwind/integration` compiles your styles
during development and builds. `@stillwind/cli` checks your styles from the command line.
## Create a stylesheet
Create `src/stillwind.css`:
```css
@import "stillwind";
@theme {
--color-accent: oklch(0.6 0.2 250);
}
```
`@import "stillwind"` loads the default Tailwind CSS v4 theme and utilities.
Each token in `@theme` adds utilities. For example, `--color-accent` adds
`bg-accent` and `text-accent`.
## Configure the project
Create `stillwind.config.ts` in the application root:
```ts title="stillwind.config.ts"
import { defineConfig } from "stillwind/config";
export default defineConfig({
projects: [
{
css: "./src/stillwind.css",
files: ["src/**/*.{ts,tsx,vue,svelte,astro}"],
},
],
});
```
`css` selects the stylesheet. `files` selects the files that the CLI and the
editor check.
> **Builds ignore files**
>
> The build compiles every module that your application imports, whether or not `files` matches it.
> The CLI and the language server (LSP) use `files` to find source files, including files that the
> application does not import.
Add Stillwind to `vite.config.ts`:
```ts
import { stillwind } from "@stillwind/integration/vite";
import react from "@vitejs/plugin-react";
import { defineConfig } from "vite";
export default defineConfig({
plugins: [stillwind(), react()],
});
```
Place `stillwind()` before `react()`. Stillwind must compile styles before React
compiles JSX. The plugin finds `stillwind.config.ts` in the application root.
## Style a component
```tsx
import { style } from "stillwind/react";
export function SaveButton({ loading }: { loading: boolean }) {
return (
);
}
```
`style()` returns props, such as `className`, so you spread the result onto the
element. Each argument adds utilities. `loading && "opacity-60"` adds
`opacity-60` only while `loading` is true.
Start the development server. The button uses the accent color from your
stylesheet. The build writes the CSS for these utilities to a static CSS file.
## Check your styles
Change `bg-accent` to `bg-acent`, and run the CLI from the application root:
```sh
vp exec stillwind lint
```
The CLI reports `bg-acent` as an unknown utility. The build does not report this
mistake: the misspelled utility produces no CSS, and the page still renders.
Run the CLI in CI to catch such mistakes before you merge them.
## Next steps
- [Why Stillwind](/docs/why): what Stillwind checks and why
- [The basics of style()](/docs/guides/style): variants, conditions, and reusable styles
- [Design systems](/docs/guides/design-systems): how to restrict colors, spacing, and breakpoints to your theme
- [Checks in the editor and CI](/docs/guides/lint-adoption): how to run the checks in CI and the editor
- [Editors](/docs/editors): how to install the extension
- [Formatters](/docs/formatters): how to sort utilities with your formatter
## Set up with an AI agent
[Coding agents](/docs/agents) gives a prompt that sets up Stillwind or migrates
an existing project. The `stillwind` package includes this documentation and
skills for the agent.
# Coding agents
> Let a coding agent set up Stillwind or migrate a project, using the documentation and skills in the stillwind package.
Source: https://stillwind.dev/docs/agents · Markdown: https://stillwind.dev/docs/agents/index.md
The `stillwind` package includes this documentation as Markdown files in
`node_modules/stillwind/docs/`. It also includes skills for coding agents. An
agent that reads these files uses the documentation of the installed version.
## Start with a prompt
Give this prompt to your agent in a new or an existing project:
```text
Set up Stillwind in this project. If the stillwind package is not installed,
install it with the project's package manager. Then read
node_modules/stillwind/docs/agents.md and follow its instructions for agents.
```
The agent decides whether the project needs a new setup or a migration. Before
it migrates existing styles, it explains the options and asks how far to go.
## What the package includes
| Path | Content |
| ------------------------------ | ------------------------------------------------------------ |
| `docs/` | This documentation as Markdown |
| `skills/setup-stillwind/` | A skill that sets up Stillwind in a project without styles |
| `skills/migrate-to-stillwind/` | A skill that migrates Tailwind CSS or other CSS to Stillwind |
| `skills/stillwind/` | A skill for everyday work in a project that uses Stillwind |
| `AGENTS_TEMPLATE.md` | A section for the instruction file of your project |
## Instructions for agents
1. Inspect the project. Find the package manager, the build tool, the framework,
and the current styling. In a monorepo, find the application that the user
means.
2. Choose a skill and follow its `SKILL.md`. The skills are in
`node_modules/stillwind/skills/`:
- Use `setup-stillwind` when the project has no styles to migrate, such as a
new project.
- Use `migrate-to-stillwind` when the project uses Tailwind CSS, plain CSS,
CSS Modules, a preprocessor, or CSS-in-JS.
3. Tell the user which skill you chose and why, in one sentence.
For later work in a project that uses Stillwind, follow `skills/stillwind/SKILL.md`.
## Install the skills
Agents can read the skills from `node_modules/stillwind/skills/` without
installation. To let your agent load them automatically, link them into its
skill directory, such as `.claude/skills/` for Claude Code or `.agents/skills/`
for Codex:
```sh
mkdir -p .claude/skills
ln -s ../../node_modules/stillwind/skills/stillwind .claude/skills/stillwind
```
A link keeps the skill in sync with the installed version. Copy the directory
instead when your system does not support links.
## Add project instructions
Add the contents of `node_modules/stillwind/AGENTS_TEMPLATE.md` to the instruction
file of your project, such as `AGENTS.md` or `CLAUDE.md`. The section tells
agents in later sessions that the project uses Stillwind and where its
documentation is.
## Read the documentation online
Every page of this website has a **View as Markdown** link. Give your agent the
[documentation index](/docs/llms.txt), or retrieve the
[full documentation](/llms-full.txt) in one request.
# At-rule reference
> Find the at-rules that define tokens, utilities, and variants in your stylesheet, and read their syntax and output.
Source: https://stillwind.dev/docs/at-rules · Markdown: https://stillwind.dev/docs/at-rules/index.md
Your stylesheet defines the design system that `style()` uses. Besides ordinary
CSS, it can contain at-rules that define tokens, utilities, and variants, and
at-rules that control where the generated CSS goes. Some of them come from
Tailwind CSS v4, and Stillwind evaluates them with its own rules. The others
start with `@stillwind-`.
Each page shows the syntax of an at-rule and examples. An example shows the
stylesheet, the source that uses it, and the complete generated stylesheet. The
generated stylesheet on these pages leaves out the preflight reset.
## Define the design system
| At-rule | Use it to | Origin |
| ---------------------------------------------------------------------------- | ------------------------------------------------------------- | --------- |
| [@theme](/docs/at-rules/theme) | Define design tokens and shared values | Tailwind |
| [@utility](/docs/at-rules/utility) | Define a utility or add declarations to an existing one | Tailwind |
| [@custom-variant](/docs/at-rules/custom-variant) | Define a variant | Tailwind |
| [@slot](/docs/at-rules/slot) | Mark where a variant definition inserts the styled content | Tailwind |
| [@plugin](/docs/at-rules/plugin) | Load a Stillwind or Tailwind CSS v4 plugin | Tailwind |
| [@stillwind-property](/docs/at-rules/stillwind-property) | Register a custom property that utilities need | Stillwind |
| [@stillwind-require-properties](/docs/at-rules/stillwind-require-properties) | Declare the registered custom properties that a utility needs | Stillwind |
## Use utilities in your own rules
| At-rule | Use it to | Origin |
| ---------------------------------- | ----------------------------------------------------- | -------- |
| [@apply](/docs/at-rules/apply) | Insert the declarations of utilities into a rule | Tailwind |
| [@variant](/docs/at-rules/variant) | Apply variants, such as `hover` or `dark`, to a block | Tailwind |
## Place the generated CSS
| At-rule | Use it to | Origin |
| ---------------------------------------------------------------- | ------------------------------------------------------ | --------- |
| [@stillwind-slot](/docs/at-rules/stillwind-slot) | Place generated utilities, theme values, and other CSS | Stillwind |
| [@stillwind-css-template](/docs/at-rules/stillwind-css-template) | Define the output of `style.css()` | Stillwind |
`@import "stillwind"` already places every slot. Use these at-rules when you
write your own entry stylesheet or change the output of `style.css()`.
## Remove or limit definitions
| At-rule | Use it to | Origin |
| ---------------------------------------------------------------------------------------- | -------------------------------------------------------- | --------- |
| [@stillwind-undef-utility](/docs/at-rules/stillwind-undef-utility) | Remove built-in or plugin utilities | Stillwind |
| [@stillwind-undef-variant](/docs/at-rules/stillwind-undef-variant) | Remove built-in or plugin variants | Stillwind |
| [@stillwind-undef-arbitrary-property](/docs/at-rules/stillwind-undef-arbitrary-property) | Reject arbitrary properties such as `[color:red]` | Stillwind |
| [@stillwind-registry](/docs/at-rules/stillwind-registry) | Change definitions only in keyframes or view transitions | Stillwind |
## Write a utility library
Stillwind's built-in utilities and variants use
[registry directives](/docs/at-rules/registry-directives), such as
`@stillwind-utility` and `@stillwind-theme-namespace`. Read them when you write
a utility library or read the built-in definitions. Application stylesheets
normally do not need them.
## Tailwind CSS features that Stillwind ignores
Stillwind reads its settings from `stillwind.config.ts` and generates utilities
only from `style()` calls. It ignores `@config`, `@source`, `@reference`, the
`important`, `source`, and `prefix` modifiers of `@import`, and the `prefix()`
option of `@theme`. [ignored-tailwind-feature](/docs/lints/ignored-tailwind-feature)
reports them.
When the loader cannot use a Stillwind at-rule, it skips the statement and
compiles the rest of the stylesheet.
[invalid-css-directive](/docs/lints/invalid-css-directive) reports the skipped
statement.
# @apply
> Insert the declarations of utilities, including their variants, into a rule of your stylesheet.
Source: https://stillwind.dev/docs/at-rules/apply · Markdown: https://stillwind.dev/docs/at-rules/apply/index.md
```css
selector {
@apply utilities;
}
```
`@apply` replaces itself with the declarations of the listed utilities. Write it
inside a style rule or a utility definition. Whitespace separates the utilities.
## Example
### Stylesheet
```css
.button {
@apply rounded-md px-4 py-2 hover:bg-blue-600 focus-visible:outline-2;
}
```
### Generated stylesheet without preflight
```css
/*! 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-blue-600: oklch(54.6% .245 262.881);
--spacing: .25rem;
--radius-md: .375rem;
}
}
@layer properties {
@supports (((-webkit-hyphens: none)) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color: rgb(from red r g b)))) {
*, :before, :after, ::backdrop {
--tw-outline-style: solid;
}
}
}
@property --tw-outline-style {
syntax: "*";
inherits: false;
initial-value: solid;
}
.button {
padding-inline: calc(var(--spacing) * 4);
padding-block: calc(var(--spacing) * 2);
border-radius: var(--radius-md);
&:hover {
@media (hover: hover) {
background-color: var(--color-blue-600);
}
}
&:focus-visible {
outline-style: var(--tw-outline-style);
outline-width: 2px;
}
}
```
A utility with variants becomes nested rules, and the selector of the enclosing
rule takes the place of the generated class. Utilities without variants come
first in utility order. Utilities with variants follow in variant order.
The stylesheet declares the theme values and registered properties that the
applied utilities need, as it does for `style()`.
## Rules
- A utility that does not resolve adds nothing. `.button { @apply unknown-x; }`
becomes `.button {}`.
- An applied utility can apply other utilities. A circular application is a
compilation error.
- In a utility definition, `@apply` expands after the variants of the utility
apply, so the applied declarations stay under them.
- `@apply` adds no class to any element. `@apply group` does not make the
element a `group` for `group-hover:`.
To apply a condition to your own declarations, use
[@variant](/docs/at-rules/variant) instead.
# @custom-variant
> Define a variant with a selector, or with a block that marks the styled content with @slot.
Source: https://stillwind.dev/docs/at-rules/custom-variant · Markdown: https://stillwind.dev/docs/at-rules/custom-variant/index.md
```css
@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
```css
@custom-variant theme-dark (&:where([data-theme="dark"], [data-theme="dark"] *));
@custom-variant hocus {
&:hover,
&:focus-visible {
@slot;
}
}
```
### Source
```tsx
import { style } from "stillwind/react";
export const link = style("theme-dark:text-white hocus:underline");
```
### Compiled code
```ts
export const link = {className:"sw_r7v8w"};
```
### Generated stylesheet without preflight
```css
/*! 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](/docs/lints/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
```css
@custom-variant shell scope(document) (:host);
```
### Source
```tsx
import { style } from "stillwind/react";
export const css = style.css("shell:block shell:p-4 [button]:rounded-md");
```
### Compiled code
```ts
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](/docs/lints/document-scoped-selector) reports it.
## Definitions with the same name
A later variant definition with the same name replaces the earlier one.
[duplicate-definition](/docs/lints/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.
# @plugin
> Load a Stillwind plugin or a Tailwind CSS v4 JavaScript plugin, with optional options.
Source: https://stillwind.dev/docs/at-rules/plugin · Markdown: https://stillwind.dev/docs/at-rules/plugin/index.md
```css
@plugin "name";
@plugin "name" {
option: value;
}
```
`@plugin` loads JavaScript that generates CSS definitions, and the generated CSS
replaces the statement. Write it at the top level of the stylesheet.
## Example
```css
@import "stillwind";
@plugin "@stillwind/plugin-iconify";
```
[`@stillwind/plugin-iconify`](/docs/plugins/iconify) adds icon utilities such as
`icon-mdi--close`. Only the icons that your modules use reach the stylesheet.
## Finding the plugin
The host looks up `name` in the `plugins` field of the project in
`stillwind.config.ts` first. Otherwise, it imports the package or the local file
from the stylesheet and uses its default export. See
[Configuration](/docs/configuration).
## Options
The block contains only `name: value;` declarations. Strings keep their quotes,
so a `;` inside a string does not end a declaration. The loader rejects other
statements and empty values.
## Tailwind CSS plugins
Tailwind CSS v4 JavaScript plugins use the same statement, including plugins
that `plugin.withOptions()` creates. The host supports `addBase`,
`addUtilities`, `addComponents`, `matchUtilities`, `matchComponents`,
`addVariant`, `matchVariant`, `theme`, `config`, and `prefix`. `prefix` returns
the class name unchanged, because Stillwind has no class prefix. These plugins need
the `tailwindcss` package.
The options block converts values as Tailwind does. `true`, `false`, `null`, and
numeric text become those values. A quoted string loses its quotes, other text stays
a string, and a comma-separated list becomes an array.
Definitions from a plugin register before the definitions of your stylesheet,
wherever the `@plugin` statement stands. A `@utility` in your stylesheet
therefore adds to a plugin utility with the same name, and
[@stillwind-undef-utility](/docs/at-rules/stillwind-undef-utility) can remove
plugin utilities.
A plugin can select elements by fixed class names, such as `not-prose`. `style()`
keeps these class names, as
[Tailwind CSS compatibility](/docs/guides/tailwind-compatibility#class-names-that-a-plugins-selectors-use)
describes. That page also lists the tested plugins.
A CSS package does not use `@plugin`. Load it with `@import`, such as
`@import "tw-animate-css";`.
[invalid-css-import](/docs/lints/invalid-css-import) reports a plugin that the
host cannot find or load, and invalid options. The stylesheet loads without that
plugin.
# Registry directives
> Read the at-rules that define Stillwind's built-in utilities, variants, and theme metadata.
Source: https://stillwind.dev/docs/at-rules/registry-directives · Markdown: https://stillwind.dev/docs/at-rules/registry-directives/index.md
Stillwind defines its built-in utilities and variants in CSS, in the files that
`@import "stillwind"` loads. These files use registry directives, which describe
cascade order, theme metadata, and other information that ordinary definitions
cannot express. Use them when you write a utility library. An application
stylesheet normally uses [@utility](/docs/at-rules/utility) and
[@custom-variant](/docs/at-rules/custom-variant) instead.
Editors suggest these directives inside definitions and registry blocks. The
[built-in definitions](https://github.com/SegaraRai/stillwind/tree/main/packages/core/css)
show complete examples.
## Definitions
### @stillwind-utility
```css
@stillwind-utility name-* (tw-sort: property) { ... }
```
Defines a utility with the same body language as `@utility`. The position of the
definition decides its cascade order: a later definition wins over an earlier
one when both set the same property. The optional `tw-sort` descriptor names the
property that Tailwind-compatible class sorting uses for the definition. The
header also accepts `implementation`.
All `@stillwind-utility` definitions of a name register before plugin
definitions and the `@utility` definitions of the stylesheet.
### @stillwind-variant
```css
@stillwind-variant name (descriptors) { ... }
```
Defines a variant with the body language of `@custom-variant`. Its position
decides the output order of variant rules. The optional header is a
comma-separated list:
| Descriptor | Value |
| ----------- | ----------------------------------------------------------------------------------------- |
| `value` | The accepted value type of a `*` name, such as `[supports-condition]` |
| `modifier` | The accepted modifier type |
| `scope` | `document`, which keeps selectors without `&` as written |
| `sort` | A theme namespace, such as `--breakpoint-*`, whose token values order the variants |
| `direction` | `asc` or `desc`, the order of the `sort` values |
| `group` | A group name. Variants of a group are ordered together, at the position of the first one. |
| `bare` | `true` when the variant also matches a bare token name, such as `lg` for `min-lg` |
```css
@stillwind-variant min-* (sort: --breakpoint-*, direction: asc, bare: true) {
@media (width >= --value(--breakpoint-*)) {
@slot;
}
}
```
### @stillwind-intrinsic
```css
@stillwind-intrinsic name;
```
Replaces the body of a `@stillwind-variant` with a behavior that the compiler
implements, such as `not-*`. The names are internal to Stillwind.
### @stillwind-arbitrary-property
```css
@stillwind-arbitrary-property pattern;
```
Places arbitrary-property candidates for the matching properties, such as
`[color:red]`, at this position in the cascade order of utilities. The built-in
definitions end with `@stillwind-arbitrary-property *;`, so other arbitrary
properties come after every built-in utility. The statement also accepts the
matching properties again after
[@stillwind-undef-arbitrary-property](/docs/at-rules/stillwind-undef-arbitrary-property).
## Theme metadata
### @stillwind-theme-namespace
```css
@stillwind-theme-namespace --spacing-* [length] scale(px: 1px);
```
Declares a theme namespace. The bracketed types limit the arbitrary values and
typed variables that the namespace accepts.
[incompatible-theme-value](/docs/lints/incompatible-theme-value) uses them to
check tokens.
`scale()` makes the token with the namespace name, such as `--spacing`, the scale
of the namespace. A numeric key then resolves to a multiple of the scale, and
`--spacing(4)` lowers to the same multiple. Each argument of `scale()` names a
key with a fixed value, such as `px` for `1px`.
### @stillwind-theme-exclude
```css
@stillwind-theme-exclude --text-* --text-shadow-*;
```
Makes a `--value(--text-*)` pattern skip the tokens of the narrower namespaces
that follow the first one. Without it, `--text-shadow-lg` would be a value of
`--text-*`.
### @stillwind-theme-order
```css
@stillwind-theme-order spacing color;
```
Sets the order of namespaces in the declarations that the `theme` slot emits.
### @stillwind-omit-token-prefix
```css
@stillwind-omit-token-prefix --shadow- --tw-shadow:;
```
Leaves out the tokens with the prefix when the generated CSS contains the
condition text.
## Values and dependencies
### @stillwind-format
```css
@stillwind-format transform compose-space;
@stillwind-format --tw-translate-* zero-length;
```
Declares how the compiler treats the values of the matching properties.
`compose-space` marks a property whose declarations compose space-separated
parts. `zero-length` gives a zero value the length type that `calc()` needs.
## Classes and relationships
### @stillwind-marker
```css
@stillwind-marker group (modifiable);
```
Declares a marker class: a class that a candidate adds to the element as
written, so that selectors such as `.group:hover &` can match it. `modifiable`
also accepts a named modifier, so `group/menu` adds the class `group/menu`.
The classes that the selectors of `@utility` and `@custom-variant` definitions
name are also marker classes.
[invalid-marker-use](/docs/lints/invalid-marker-use) reports a candidate that
names a marker class but cannot add it, such as `hover:group`.
### @stillwind-marker-source
```css
@stillwind-marker-source ".card .title {}";
```
Makes the classes that the rules in the string select marker classes, as a
definition body does. It defines and emits nothing. Plugins use it for classes
that their dynamic utilities use.
### @stillwind-relationship
```css
@stillwind-relationship group-*;
```
Registers a pattern of utility or variant names that relate an element to
another element, such as `group-*` and `peer-*`.
[prefer-typed-relationships](/docs/lints/prefer-typed-relationships) reports
candidates that match a pattern, because [style.ref()](/docs/macros/ref) can
express the same relationship. The patterns do not change the generated CSS.
# @slot
> Mark where a variant definition inserts the styled content.
Source: https://stillwind.dev/docs/at-rules/slot · Markdown: https://stillwind.dev/docs/at-rules/slot/index.md
```css
@slot;
```
`@slot` marks where the block form of a variant definition inserts the
declarations of the utility. Write it in the body of
[@custom-variant](/docs/at-rules/custom-variant), or of a registry variant
definition.
### Stylesheet
```css
@custom-variant hocus {
&:hover,
&:focus-visible {
@slot;
}
}
```
### Source
```tsx
import { style } from "stillwind/react";
export const link = style("hocus:underline");
```
### Compiled code
```ts
export const link = {className:"sw_4x5c3"};
```
### Generated stylesheet without preflight
```css
/*! 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 utilities {
.sw_4x5c3:hover, .sw_4x5c3:focus-visible {
text-decoration-line: underline;
}
}
```
`@slot` belongs to variant definitions only.
[@stillwind-slot](/docs/at-rules/stillwind-slot) is a different at-rule: it
places generated CSS in your stylesheet.
# @stillwind-css-template
> Define where style.css() places its utilities, theme values, and other supporting CSS.
Source: https://stillwind.dev/docs/at-rules/stillwind-css-template · Markdown: https://stillwind.dev/docs/at-rules/stillwind-css-template/index.md
```css
@stillwind-css-template name {
...
@stillwind-slot utilities;
}
```
`@stillwind-css-template` defines a template for the string that
[style.css()](/docs/macros/css) returns. The `template` option of the call
selects the template by name, and `default` applies when the call names none.
Write it at the top level of the stylesheet.
## Example
### Stylesheet
```css
@stillwind-css-template layered {
@layer component {
:host {
@stillwind-slot theme;
}
@stillwind-slot utilities;
}
}
```
### Source
```tsx
import { style } from "stillwind/react";
export const css = style.css("p-4 text-blue-600", {
selector: ":host",
template: "layered",
});
```
### Compiled code
```ts
export const css = "/*! stillwind v0.0.0 | MIT License | https://stillwind.dev */\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n@layer component{:host{--color-blue-600:oklch(54.6% 0.245 262.881);--spacing:0.25rem;}:host{padding:calc(var(--spacing) * 4);}:host{color:var(--color-blue-600);}}";
```
The string contains the template's own CSS, and each slot receives the output of
the call. The string never contains the preflight reset or the other rules of
your stylesheet.
## Leave out supporting CSS
A slot that the template omits drops its output. This template places only the
utilities, so the string uses `--spacing` and `--color-blue-600` without
declaring them. The page or the shadow root must declare them in another way.
### Stylesheet
```css
@stillwind-css-template bare {
@stillwind-slot utilities;
}
```
### Source
```tsx
import { style } from "stillwind/react";
export const css = style.css("p-4 text-blue-600", {
selector: ":host",
template: "bare",
});
```
### Compiled code
```ts
export const css = "/*! stillwind v0.0.0 | MIT License | https://stillwind.dev */\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n:host{padding:calc(var(--spacing) * 4);}:host{color:var(--color-blue-600);}";
```
## The default template
`@import "stillwind"` defines `default`:
```css
@stillwind-css-template default {
:where(:root, :host) {
@stillwind-slot theme;
@stillwind-slot property-initials inherited;
}
:where(*, :host),
::before,
::after,
::backdrop {
@stillwind-slot property-initials non-inherited;
}
@stillwind-slot keyframes;
@stillwind-slot utilities;
}
```
It places the theme values on the root of the tree that adopts the string. It
emits no `@property` rules, because a registration inside a shadow root has no
effect. No rule is in a layer.
A later template with the same name replaces an earlier one, so your stylesheet
can redefine `default` after `@import "stillwind"`.
## Rules
- A template must contain a `utilities` slot.
- A template cannot contain definitions, such as `@theme` or `@utility`.
- The loader skips a template that breaks these rules, and
[invalid-css-directive](/docs/lints/invalid-css-directive) reports it.
- A template name that the stylesheet does not define reports
[invalid-css-input](/docs/lints/invalid-css-input) at the call. The call then
uses no template, and its string contains only the rules.
# @stillwind-property
> Register a custom property that the stylesheet declares with @property only when generated CSS needs it.
Source: https://stillwind.dev/docs/at-rules/stillwind-property · Markdown: https://stillwind.dev/docs/at-rules/stillwind-property/index.md
```css
@stillwind-property --name {
syntax: "";
inherits: false;
initial-value: 0deg;
}
```
`@stillwind-property` registers a custom property. The compiler emits a
standard `@property` rule, and an initial value for each element, only when the
generated CSS needs the property. Write it at the top level of the stylesheet.
## Example
### Stylesheet
```css
@stillwind-property --spin-angle {
syntax: "";
inherits: false;
initial-value: 0deg;
}
@utility spin-* {
--spin-angle: --value([angle]);
rotate: var(--spin-angle);
}
```
### Source
```tsx
import { style } from "stillwind/react";
export const icon = style("spin-[45deg]");
```
### Compiled code
```ts
export const icon = {className:"sw_7ic77"};
```
### Generated stylesheet without preflight
```css
/*! 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 utilities {
.sw_7ic77 {
--spin-angle: 45deg;
rotate: var(--spin-angle);
}
}
@layer properties {
@supports (((-webkit-hyphens: none)) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color: rgb(from red r g b)))) {
*, :before, :after, ::backdrop {
--spin-angle: 0deg;
}
}
}
@property --spin-angle {
syntax: "";
inherits: false;
initial-value: 0deg;
}
```
The `properties` slot places the `@property` rule. The `property-initials` slot
places the initial values, for browsers that ignore `@property`. See
[@stillwind-slot](/docs/at-rules/stillwind-slot).
## Descriptors
The standard `@property` descriptors, `syntax`, `inherits`, and `initial-value`,
go into the emitted rule as written. The compiler reads the other descriptors and
removes them from the output:
| Descriptor | Value |
| ------------- | ------------------------------------------------------------------------------------------ |
| `activation` | When to emit: `referenced` (default), `declared`, `either`, or `dependency` |
| `depends-on` | Space-separated custom properties that are emitted with this one |
| `group` | Space-separated group names. The registrations of a group are emitted together. |
| `activate-on` | Space-separated ordinary properties. A declaration of one of them emits this registration. |
| `value-for` | Comma-separated ordinary properties whose value rules check the values of this property |
`referenced` emits the registration when a rule reads the property through
`var()`. `declared` emits it when a rule sets the property. `either` emits it in
both cases. `dependency` emits it only through `depends-on` or `group`.
A utility can also require a registration with
[@stillwind-require-properties](/docs/at-rules/stillwind-require-properties).
## Value checks
`value-for` makes lint rules check the value of the custom property as a value
of the listed properties:
```css
@stillwind-property --box-size {
syntax: "*";
inherits: false;
value-for: width, height;
}
@utility box-* {
--box-size: --value([length]);
}
```
[no-arbitrary-spacing](/docs/lints/no-arbitrary-spacing),
[no-arbitrary-colors](/docs/lints/no-arbitrary-colors), and
[no-restricted-length-units](/docs/lints/no-restricted-length-units) check
`box-[13px]` as a `width` and a `height` value. Each listed property uses its own
rule settings.
## Registrations with the same name
The last registration of a name decides. A registration in your stylesheet
replaces the registration of a package. An ordinary `@property` rule in your
stylesheet stays as written, and the compiler does not emit a registration with
the same name.
# @stillwind-registry
> Define or remove utilities only for style(), keyframes, animation options, or view transitions.
Source: https://stillwind.dev/docs/at-rules/stillwind-registry · Markdown: https://stillwind.dev/docs/at-rules/stillwind-registry/index.md
```css
@stillwind-registry default, keyframe, animation, view-transition {
...
}
```
Each place where utilities are written resolves them with its own set of
definitions, called a registry. `@stillwind-registry` selects the registries
that the definitions inside the block change. Write it at the top level of the
stylesheet, or inside another `@stillwind-registry` block.
| Registry | Resolves the utilities of |
| ----------------- | ----------------------------------------------------------------------------- |
| `default` | `style()`, `style.cva()`, `style.css()`, and `@apply` |
| `keyframe` | The frames of `style.keyframes()` |
| `animation` | The options of a keyframes use, such as `enter("both")` |
| `view-transition` | The `group`, `old`, `new`, and `imagePair` fields of `style.viewTransition()` |
A definition outside every block changes `default`, `keyframe`, and
`view-transition`. `animation` starts empty and changes only through blocks that
name it.
## Example
The built-in `keyframe` and `view-transition` registries replace `duration-*`
with definitions that set animation properties. A top-level `@utility` with a
name that they replace also reaches those registries, and
[bypassed-undefinition](/docs/lints/bypassed-undefinition) reports it. A
`default` block keeps the definition out of them:
### Stylesheet
```css
@stillwind-registry default {
@utility duration-slow {
transition-duration: 600ms;
}
}
```
### Source
```tsx
import { style } from "stillwind/react";
export const panel = style("transition duration-slow");
```
### Compiled code
```ts
export const panel = {className:"sw_2wahw"};
```
### Generated stylesheet without preflight
```css
/*! 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 {
--default-transition-duration: .15s;
--default-transition-timing-function: cubic-bezier(.4, 0, .2, 1);
}
}
@layer utilities {
.sw_2wahw {
transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to, opacity, box-shadow, transform, translate, scale, rotate, filter, -webkit-backdrop-filter, backdrop-filter, display, content-visibility, overlay, pointer-events;
transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
transition-duration: var(--tw-duration, var(--default-transition-duration));
transition-duration: .6s;
}
}
```
A block that names `animation` and `view-transition` defines the utility for
animations instead:
```css
@stillwind-registry animation, view-transition {
@utility duration-slow {
animation-duration: 600ms;
}
}
```
## Contents
A block contains only these statements. Another statement is an error.
- `@utility`, `@custom-variant`, and `@variant` definitions
- [@stillwind-undef-utility](/docs/at-rules/stillwind-undef-utility),
[@stillwind-undef-variant](/docs/at-rules/stillwind-undef-variant), and
[@stillwind-undef-arbitrary-property](/docs/at-rules/stillwind-undef-arbitrary-property)
- `@stillwind-arbitrary-property`, `@stillwind-utility`, and
`@stillwind-variant` from the [registry directives](/docs/at-rules/registry-directives)
- A nested `@stillwind-registry` block. The innermost block decides.
The header names one or more registries, separated by commas. An unknown or
missing name is an error, and
[invalid-css-directive](/docs/lints/invalid-css-directive) reports it.
[Animations](/docs/guides/animations) and
[View transitions](/docs/guides/view-transitions) show how utilities such as
`duration-300` set animation properties in those registries.
# @stillwind-require-properties
> Make a utility emit the registrations of custom properties that it needs.
Source: https://stillwind.dev/docs/at-rules/stillwind-require-properties · Markdown: https://stillwind.dev/docs/at-rules/stillwind-require-properties/index.md
```css
@utility name {
@stillwind-require-properties --name --other;
}
```
`@stillwind-require-properties` adds registrations to the requirements of a
utility. When a module uses the utility, the stylesheet emits each listed
registration. Write it in the body of a utility definition. Separate several
names with spaces.
## Example
`spin-*` only sets `--spin-angle`, and another rule reads it. Without the
requirement, the stylesheet would not emit the registration, because the default
activation waits for a `var()` reference.
### Stylesheet
```css
@stillwind-property --spin-angle {
syntax: "";
inherits: false;
initial-value: 0deg;
}
@utility spin-* {
@stillwind-require-properties --spin-angle;
--spin-angle: --value([angle]);
}
```
### Source
```tsx
import { style } from "stillwind/react";
export const icon = style("spin-[45deg]");
```
### Compiled code
```ts
export const icon = {className:"sw_7ic77"};
```
### Generated stylesheet without preflight
```css
/*! 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 utilities {
.sw_7ic77 {
--spin-angle: 45deg;
}
}
@layer properties {
@supports (((-webkit-hyphens: none)) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color: rgb(from red r g b)))) {
*, :before, :after, ::backdrop {
--spin-angle: 0deg;
}
}
}
@property --spin-angle {
syntax: "";
inherits: false;
initial-value: 0deg;
}
```
## Errors
Each name must be a complete custom property name that starts with `--`. The
compiler reports an invalid name as [SW14003](/docs/errors/SW14003) in your
stylesheet. When a module uses a utility with an invalid name, the compiler
reports [SW14004](/docs/errors/SW14004), including for plugin utilities.
A required name needs a [@stillwind-property](/docs/at-rules/stillwind-property)
registration in the loaded stylesheets. A missing registration is
[SW14005](/docs/errors/SW14005).
# @stillwind-slot
> Place generated utilities, theme values, keyframes, and property registrations in your stylesheet.
Source: https://stillwind.dev/docs/at-rules/stillwind-slot · Markdown: https://stillwind.dev/docs/at-rules/stillwind-slot/index.md
```css
@stillwind-slot name;
```
`@stillwind-slot` marks where the compiler writes one kind of generated CSS.
`@import "stillwind"` already places every slot, so you need this at-rule only
when you write your own entry stylesheet or a
[CSS template](/docs/at-rules/stillwind-css-template).
## Slots
These slots insert complete rules. Write them outside style rules:
| Slot | Inserts |
| ------------ | --------------------------------------------------- |
| `utilities` | The rules of the utilities that modules use |
| `keyframes` | The `@keyframes` rules that the used utilities need |
| `properties` | The `@property` rules of the needed registrations |
These slots insert declarations. Write them inside a style rule, which supplies
the selector:
| Slot | Inserts |
| --------------------------------- | -------------------------------------------------------------------------- |
| `theme` | The theme values that the generated CSS uses, and `@theme static` values |
| `property-initials` | The initial values of the needed registrations |
| `property-initials inherited` | The initial values of the needed registrations with `inherits: true` only |
| `property-initials non-inherited` | The initial values of the needed registrations with `inherits: false` only |
## Example
`@import "stillwind"` places the slots like this, in simplified form:
```css
@layer properties, theme, base, components, utilities;
@layer theme {
:root,
:host {
@stillwind-slot theme;
}
@stillwind-slot keyframes;
}
@layer utilities {
@stillwind-slot utilities;
}
@layer properties {
*,
::before,
::after,
::backdrop {
@stillwind-slot property-initials;
}
}
@stillwind-slot properties;
```
The position of a slot decides the cascade order of its output. An enclosing
`@layer` or conditional at-rule also applies to the output. Moving
`utilities` before your own rules, or into another layer, can change which
declarations win.
## Rules
- A slot with an unknown name, or in a position that cannot contain its output,
is skipped. [invalid-css-directive](/docs/lints/invalid-css-directive) reports
it.
- A stylesheet without a `utilities` slot is [SW14001](/docs/errors/SW14001).
A missing slot for other generated CSS that a module needs, such as
`keyframes`, is [SW14002](/docs/errors/SW14002).
- A repeated slot repeats its output at every position.
`@stillwind-slot` places generated CSS. [@slot](/docs/at-rules/slot) is a
different at-rule for variant definitions.
# @stillwind-undef-arbitrary-property
> Reject arbitrary-property utilities such as [color:red] for the properties that match a pattern.
Source: https://stillwind.dev/docs/at-rules/stillwind-undef-arbitrary-property · Markdown: https://stillwind.dev/docs/at-rules/stillwind-undef-arbitrary-property/index.md
```css
@stillwind-undef-arbitrary-property property;
@stillwind-undef-arbitrary-property prefix-*;
@stillwind-undef-arbitrary-property *;
```
An arbitrary property is a utility that writes a declaration directly, such as
`[color:red]`. `@stillwind-undef-arbitrary-property` rejects arbitrary
properties for the matching CSS properties. A rejected candidate produces no
CSS. Write the statement at the top level of the stylesheet or in a
[@stillwind-registry](/docs/at-rules/stillwind-registry) block.
## Example
### Stylesheet
```css
@stillwind-undef-arbitrary-property *;
@stillwind-arbitrary-property --*;
```
### Source
```tsx
import { style } from "stillwind/react";
export const rejected = style("[color:red]");
export const accepted = style("[--gutter:1rem]");
```
### Compiled code
```ts
export const rejected = {};
export const accepted = {className:"sw_obysi"};
```
### Generated stylesheet without preflight
```css
/*! 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 utilities {
.sw_obysi {
--gutter: 1rem;
}
}
```
The first statement rejects every property. The second statement accepts custom
properties again, so components can still set variables.
## Rules
- The last matching statement decides for each property. A property that no
statement matches is accepted.
- `@stillwind-arbitrary-property pattern;` accepts the matching properties
again. The [registry directives](/docs/at-rules/registry-directives) describe
its other role.
- Patterns use the same forms as
[@stillwind-undef-utility](/docs/at-rules/stillwind-undef-utility), with
property names instead of utility names.
To report arbitrary values without rejecting them, use lint rules such as
[no-arbitrary-colors](/docs/lints/no-arbitrary-colors) or
[no-restricted-declarations](/docs/lints/no-restricted-declarations) instead.
# @stillwind-undef-utility
> Remove built-in or plugin utility definitions that match a name or a prefix.
Source: https://stillwind.dev/docs/at-rules/stillwind-undef-utility · Markdown: https://stillwind.dev/docs/at-rules/stillwind-undef-utility/index.md
```css
@stillwind-undef-utility name;
@stillwind-undef-utility prefix-*;
@stillwind-undef-utility *;
```
`@stillwind-undef-utility` removes the matching utility definitions that
register before it. A removed utility becomes unknown, and
[unknown-utility](/docs/lints/unknown-utility) reports its uses. Write it at the
top level of the stylesheet or in a
[@stillwind-registry](/docs/at-rules/stillwind-registry) block.
## Example
### Stylesheet
```css
@stillwind-undef-utility float-*;
@utility float-start {
float: inline-start;
}
```
### Source
```tsx
import { style } from "stillwind/react";
export const removed = style("float-left");
export const replaced = style("float-start");
```
### Compiled code
```ts
export const removed = {};
export const replaced = {className:"sw_vofby"};
```
### Generated stylesheet without preflight
```css
/*! 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 utilities {
.sw_vofby {
float: inline-start;
}
}
```
The statement removes every built-in `float-*` utility. `float-left` produces no
class, and `float-start` uses only the new definition.
## Patterns
A pattern is `*`, an exact name, or a prefix followed by `*`. `duration-*`
matches the definition `duration-*` and the exact names that start with
`duration-`, such as `duration-initial`. It does not match `-duration-*`: a
pattern for negative names starts with `-`.
## Order
The statements that `@plugin` generates register first. The other statements,
including the built-in definitions that `@import "stillwind"` loads, follow in
source order. An undefinition removes only definitions that register before it:
- It removes plugin utilities, wherever the `@plugin` statement stands.
- It removes the built-in utilities that `@import "stillwind"` loads before it.
- It does not remove a `@utility` that comes after it, so you can remove a
built-in utility and define your own utility with the same name.
A replacement with the same name keeps the cascade position of the removed
definition, so it wins against the same utilities as before. A definition with
another name takes the position where you write it. A definition without `*`
does not take the position of a removed `prefix-*` definition.
The [logical stylesheets](/docs/concepts/stylesheets#logical-axis-utilities) replace
utilities in this way.
Outside a block, the statement changes the `default`, `keyframe`, and
`view-transition` registries.
To report uses of a utility without removing it, use
[no-restricted-utilities](/docs/lints/no-restricted-utilities) instead.
# @stillwind-undef-variant
> Remove built-in or plugin variant definitions that match a name or a prefix.
Source: https://stillwind.dev/docs/at-rules/stillwind-undef-variant · Markdown: https://stillwind.dev/docs/at-rules/stillwind-undef-variant/index.md
```css
@stillwind-undef-variant name;
@stillwind-undef-variant prefix-*;
@stillwind-undef-variant *;
```
`@stillwind-undef-variant` removes the matching variant definitions that
register before it. A removed variant becomes unknown, and
[unknown-variant](/docs/lints/unknown-variant) reports its uses. Write it at the
top level of the stylesheet or in a
[@stillwind-registry](/docs/at-rules/stillwind-registry) block.
## Example
### Stylesheet
```css
@stillwind-undef-variant print;
```
### Source
```tsx
import { style } from "stillwind/react";
export const toolbar = style("print:hidden");
```
### Compiled code
```ts
export const toolbar = {};
```
### Generated stylesheet without preflight
```css
/*! stillwind v0.0.0 | MIT License | https://stillwind.dev */
/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */
@layer properties, theme, base, components, utilities;
```
`print:hidden` produces no class, because `print` is unknown.
Patterns and registration order work as in
[@stillwind-undef-utility](/docs/at-rules/stillwind-undef-utility). A
[@custom-variant](/docs/at-rules/custom-variant) after the statement can define
a variant with the removed name again.
# @theme
> Define design tokens that add utilities, and shared values such as images.
Source: https://stillwind.dev/docs/at-rules/theme · Markdown: https://stillwind.dev/docs/at-rules/theme/index.md
```css
@theme [default] [asset] [inline | static] {
--name: value;
}
```
`@theme` defines design tokens as custom properties. A token in a known
namespace adds utilities: `--color-brand` adds `bg-brand`, `text-brand`, and the
other color utilities. Write `@theme` at the top level of the stylesheet.
## Example
### Stylesheet
```css
@theme {
--color-brand: oklch(0.6 0.2 250);
--color-brand-muted: oklch(0.8 0.08 250);
--radius-card: 0.75rem;
}
```
### Source
```tsx
import { style } from "stillwind/react";
export const card = style("rounded-card bg-brand");
```
### Compiled code
```ts
export const card = {className:"sw_j7rat"};
```
### Generated stylesheet without preflight
```css
/*! 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-brand: oklch(60% .2 250);
--radius-card: .75rem;
}
}
@layer utilities {
.sw_j7rat {
background-color: var(--color-brand);
border-radius: var(--radius-card);
}
}
```
The generated stylesheet declares only the tokens that the used utilities
reference. `--color-brand-muted` is not used, so the stylesheet leaves it out.
## Options
| Option | Effect |
| --------- | ----------------------------------------------------------------------------------- |
| `default` | Marks the tokens as defaults. A token without `default` replaces them in any order. |
| `asset` | Declares shared values, such as images, that are not design tokens |
| `inline` | Replaces each `var()` reference to a token with the token's value |
| `static` | Declares the tokens even when no used utility references them |
`inline` and `static` cannot be combined. The other options can be combined
freely.
### Defaults
### Stylesheet
```css
@theme {
--color-brand: red;
}
@theme default {
--color-brand: blue;
--color-brand-muted: lightblue;
}
```
### Source
```tsx
import { style } from "stillwind/react";
export const label = style("bg-brand text-brand-muted");
```
### Compiled code
```ts
export const label = {className:"sw_4zrwj"};
```
### Generated stylesheet without preflight
```css
/*! 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-brand: red;
--color-brand-muted: lightblue;
}
}
@layer utilities {
.sw_4zrwj {
color: var(--color-brand-muted);
background-color: var(--color-brand);
}
}
```
`--color-brand` without `default` wins although it comes first. The default
theme of Stillwind uses `default`, so your tokens replace its values.
### Inline and static values
### Stylesheet
```css
@theme inline {
--font-display: "Inter Display", sans-serif;
}
@theme static {
--color-highlight: #fde047;
}
```
### Source
```tsx
import { style } from "stillwind/react";
export const title = style("font-display");
```
### Compiled code
```ts
export const title = {className:"sw_mjcfr"};
```
### Generated stylesheet without preflight
```css
/*! 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-highlight: #fde047;
}
}
@layer utilities {
.sw_mjcfr {
font-family: Inter Display, sans-serif;
}
}
```
`font-display` contains the value of `--font-display` instead of a `var()`
reference, and the stylesheet does not declare `--font-display`. The stylesheet
declares `--color-highlight`, although no utility uses it, so your own CSS can
reference it.
### Assets
### Stylesheet
```css
@theme asset {
--image-check: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'/%3E");
}
@utility checkmark {
mask-image: var(--image-check);
}
```
### Source
```tsx
import { style } from "stillwind/react";
export const done = style("checkmark");
```
### Compiled code
```ts
export const done = {className:"sw_j94hj"};
```
### Generated stylesheet without preflight
```css
/*! 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 {
--image-check: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'/%3E");
}
}
@layer utilities {
.sw_j94hj {
mask-image: var(--image-check);
}
}
```
An asset is declared when a used rule references it, like a token. An asset adds
no utilities. Token restrictions, `--value()` patterns, `theme()`, and
`--theme()` do not see assets.
## Remove tokens
Set a namespace to `initial` to remove its earlier tokens. `--*: initial`
removes every token.
### Stylesheet
```css
@theme {
--color-*: initial;
--color-ink: #1f2937;
--color-paper: #ffffff;
}
```
### Source
```tsx
import { style } from "stillwind/react";
export const page = style("bg-paper text-ink");
```
### Compiled code
```ts
export const page = {className:"sw_rjnyv"};
```
### Generated stylesheet without preflight
```css
/*! 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-ink: #1f2937;
--color-paper: #fff;
}
}
@layer utilities {
.sw_rjnyv {
color: var(--color-ink);
background-color: var(--color-paper);
}
}
```
After this block, palette utilities such as `bg-red-500` are unknown.
A reset affects only tokens of the same kind: `@theme { --*: initial; }` keeps
assets, and `@theme asset { --*: initial; }` keeps design tokens.
## Placement
The `theme` slot places the declarations. `@import "stillwind"` puts it on
`:root, :host`. See [@stillwind-slot](/docs/at-rules/stillwind-slot).
[incompatible-theme-value](/docs/lints/incompatible-theme-value) reports a token
with a value of the wrong type for its namespace, such as a length in
`--color-*`. [Design systems](/docs/guides/design-systems) shows how to name
tokens by role and report values outside them.
# @utility
> Define a utility, or add declarations to a built-in utility with the same name.
Source: https://stillwind.dev/docs/at-rules/utility · Markdown: https://stillwind.dev/docs/at-rules/utility/index.md
```css
@utility name { ... }
@utility name-* { ... }
@utility name (implementation) { ... }
```
`@utility` defines a utility for `style()`, `@apply`, and the other places that
accept utilities. Write it at the top level of the stylesheet.
## Static and functional utilities
A name without `*` defines a static utility. A name that ends in `-*` defines a
functional utility, and `--value()` reads the rest of the candidate.
### Stylesheet
```css
@utility content-auto {
content-visibility: auto;
}
@utility stack-* {
display: flex;
flex-direction: column;
gap: --spacing(--value(integer));
}
```
### Source
```tsx
import { style } from "stillwind/react";
export const list = style("content-auto stack-3");
```
### Compiled code
```ts
export const list = {className:"sw_70m3s"};
```
### Generated stylesheet without preflight
```css
/*! 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 {
--spacing: .25rem;
}
}
@layer utilities {
.sw_70m3s {
content-visibility: auto;
display: flex;
flex-direction: column;
gap: calc(var(--spacing) * 3);
}
}
```
## Values and modifiers
`--value()` lists the accepted forms of the value, and the first matching form
decides. `--modifier()` reads the part after `/` in the same way.
| Form | Accepts | Example candidate |
| -------------- | ------------------------------ | ----------------- |
| `--tab-size-*` | A token of the namespace | `tab-width-wide` |
| `integer` | A bare value of the type | `tab-width-2` |
| `[integer]` | An arbitrary value of the type | `tab-width-[3]` |
### Stylesheet
```css
@theme {
--tab-size-wide: 8;
}
@utility tab-width-* {
tab-size: --value(--tab-size-*, integer, [integer]);
}
@utility text-fluid-* {
font-size: --value(--text-*);
line-height: --modifier(--leading-*, [length]);
}
```
### Source
```tsx
import { style } from "stillwind/react";
export const code = style("tab-width-wide text-fluid-lg/tight");
```
### Compiled code
```ts
export const code = {className:"sw_9jkuo"};
```
### Generated stylesheet without preflight
```css
/*! 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 {
--text-lg: 1.125rem;
--leading-tight: 1.25;
--tab-size-wide: 8;
}
}
@layer utilities {
.sw_9jkuo {
tab-size: var(--tab-size-wide);
font-size: var(--text-lg);
line-height: var(--leading-tight);
}
}
```
A declaration whose `--value()` matches no form is left out. A candidate that
matches no declaration produces no CSS, and
[unknown-utility](/docs/lints/unknown-utility) reports it.
## Definitions with the same name
A definition with an existing name adds its declarations to the existing
utility. It does not replace it. Every definition that accepts the candidate
contributes, and a later definition wins in the cascade.
### Stylesheet
```css
@utility container {
padding-inline: 1rem;
}
```
### Source
```tsx
import { style } from "stillwind/react";
export const page = style("container");
```
### Compiled code
```ts
export const page = {className:"sw_5yksj"};
```
### Generated stylesheet without preflight
```css
/*! 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 utilities {
.sw_5yksj {
width: 100%;
padding-inline: 1rem;
@media (width >= 40rem) {
max-width: 40rem;
}
@media (width >= 48rem) {
max-width: 48rem;
}
@media (width >= 64rem) {
max-width: 64rem;
}
@media (width >= 80rem) {
max-width: 80rem;
}
@media (width >= 96rem) {
max-width: 96rem;
}
}
}
```
A static definition replaces a functional one for its exact name:
`@utility shadow-lg { ... }` replaces the built-in `shadow-*` for `shadow-lg`
only. To remove built-in definitions, use
[@stillwind-undef-utility](/docs/at-rules/stillwind-undef-utility).
## Body
A body can contain nested rules, `@apply`, `@keyframes`, and `@property`. A
nested selector without `&` selects descendants: `[data-icon]` means
`& [data-icon]`. Variants select the utility element, and the nested selector
applies inside them.
The compiler moves `@keyframes` and `@property` rules of a used utility to the
`keyframes` slot, because browsers ignore them inside a style rule. An unused
utility adds no such rules.
To use a registered custom property, register it with
[@stillwind-property](/docs/at-rules/stillwind-property) and require it with
[@stillwind-require-properties](/docs/at-rules/stillwind-require-properties).
## The implementation descriptor
`(implementation)` marks the fixed declarations of the body as part of the
utility's implementation. The `checkImplementation` option of a lint rule decides
whether the rule checks them:
- [prefer-logical-properties](/docs/lints/prefer-logical-properties) and
[no-restricted-length-units](/docs/lints/no-restricted-length-units) skip them
unless the option is `true`. The `em` values below are skipped.
- [no-important](/docs/lints/no-important),
[no-restricted-declarations](/docs/lints/no-restricted-declarations), and
[no-restricted-theme-tokens](/docs/lints/no-restricted-theme-tokens) check them
unless the option is `false`.
### Stylesheet
```css
@utility icon-box (implementation) {
width: 1em;
height: 1em;
}
```
### Source
```tsx
import { style } from "stillwind/react";
export const icon = style("icon-box");
```
### Compiled code
```ts
export const icon = {className:"sw_smxmp"};
```
### Generated stylesheet without preflight
```css
/*! 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 utilities {
.sw_smxmp {
width: 1em;
height: 1em;
}
}
```
Declarations that read the candidate through `--value()` or `--modifier()` are
still checked. The built-in `sr-only` and `not-sr-only` utilities also use this
descriptor.
## Conditions
A definition inside `@media` or another conditional at-rule keeps its
declarations, and the compiler ignores the condition.
[ignored-definition-condition](/docs/lints/ignored-definition-condition)
reports it. Write the condition inside the body instead, or use a variant.
# @variant
> Apply variants, such as hover or dark, to a block of declarations in a rule of your stylesheet.
Source: https://stillwind.dev/docs/at-rules/variant · Markdown: https://stillwind.dev/docs/at-rules/variant/index.md
```css
selector {
@variant variant:sequence, alternative {
declarations
}
}
```
`@variant` wraps its block in the rules of the listed variants. Write it inside
a style rule.
## Example
### Stylesheet
```css
.card {
background-color: white;
@variant hover, focus-within {
background-color: var(--color-gray-50);
}
@variant dark:hover {
background-color: var(--color-gray-800);
}
}
```
### Generated stylesheet without preflight
```css
/*! 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-gray-50: oklch(98.5% .002 247.839);
--color-gray-800: oklch(27.8% .033 256.848);
}
}
.card {
background-color: #fff;
&:hover {
@media (hover: hover) {
background-color: var(--color-gray-50);
}
}
&:focus-within {
background-color: var(--color-gray-50);
}
@media (prefers-color-scheme: dark) {
&:hover {
@media (hover: hover) {
background-color: var(--color-gray-800);
}
}
}
}
```
## Rules
- Each comma-separated sequence receives its own copy of the block.
- In a sequence, the leftmost variant is the outermost one. `dark:hover` puts
the `dark` media query around the `:hover` rule.
- A sequence that does not resolve contributes nothing.
`@variant nope, print { ... }` keeps only the `print` copy.
- Nested blocks expand inside the rules of the enclosing sequences.
- A `@variant` statement without a block stays in the output unchanged.
[prefer-variant-directive](/docs/lints/prefer-variant-directive) reports an
`@media` query that a variant of your theme can replace, such as a breakpoint.
## Variant definitions
At the top level of the stylesheet, a `@variant` block that contains `@slot`
defines a variant, for compatibility with older Tailwind CSS stylesheets. Use
[@custom-variant](/docs/at-rules/custom-variant) for new definitions.
# CLI
> Commands, options, file selection, exit codes, and output formats of the Stillwind CLI.
Source: https://stillwind.dev/docs/cli · Markdown: https://stillwind.dev/docs/cli/index.md
`@stillwind/cli` sorts utilities, reports lint findings, applies automatic fixes,
and starts the language server. It reads the same `stillwind.config.ts` as the
build integration and the editor.
```sh
vp i -D @stillwind/cli
```
To run the CLI in CI, see [Checks in the editor and CI](/docs/guides/lint-adoption).
## Commands
| Command | Action |
| ---------------- | ---------------------------------------------------- |
| `stillwind fmt` | Sorts utilities |
| `stillwind lint` | Reports lint findings, and can apply automatic fixes |
| `stillwind lsp` | Starts the language server |
`stillwind --help` lists the commands, and `stillwind --help` lists the
options of a command. `stillwind --version` prints the package version. The short
forms of these options are `-h` and `-v`.
## stillwind fmt
```sh
vp exec stillwind fmt
vp exec stillwind fmt --check
```
`fmt` sorts utilities with the configured theme and
[`sort` options](/docs/configuration#sorting), and saves the changed files. It keeps
the source layout and the spelling of each token. Lint severity and suppression
comments do not affect `fmt`.
`fmt` does not change whitespace. To format whitespace too, see
[Formatters](/docs/formatters).
| Option | Effect |
| --------- | ------------------------------------------------------- |
| `--check` | Reports the files that need sorting, and saves no files |
`fmt` also accepts the [shared options](#shared-options) and
[globs](#select-files).
Text output shows a status for each listed file and a summary.
## stillwind lint
```sh
vp exec stillwind lint
vp exec stillwind lint --fix
vp exec stillwind lint --max-warnings 0
```
`lint` reports findings and saves no files. Text output shows a `help:` message when
a finding has a suggested edit. Not every suggested edit is an automatic fix.
| Option | Effect |
| -------------------- | --------------------------------------------------------------------- |
| `--fix` | Applies the enabled automatic fixes, and saves the changed files |
| `--quiet` | Hides warnings, and keeps their count in the summary |
| `--max-warnings ` | Fails when the number of warnings exceeds `n`, a non-negative integer |
`lint` also accepts the [shared options](#shared-options) and
[globs](#select-files).
`--fix` respects suppression comments. It sorts utilities only when
[prefer-sorted-utilities](/docs/lints/prefer-sorted-utilities) is enabled. It
repeats until the files stop changing, with at most ten changing passes per file.
Findings and the exit code describe the files after the last pass.
`--max-warnings` counts distinct warnings in each project, including warnings that
`--quiet` hides. When hidden warnings exceed the limit, the CLI still prints the
reason for the failure.
## stillwind lsp
```sh
vp exec stillwind lsp --stdio
```
`lsp` starts the [language server](/docs/editors#other-editors) over stdin and
stdout. `--stdio` is required, and stdout carries only protocol messages. `lsp`
accepts `--config`, but no globs.
## Shared options
`fmt` and `lint` accept these options:
| Option | Effect |
| ----------------------- | --------------------------------------------------- |
| `-c`, `--config ` | Uses this [configuration file](#select-files) |
| `--format ` | Selects the [output format](#output-formats) |
| `--color ` | Controls [colors](#colors-and-links) |
| `--hyperlinks ` | Controls [links to source files](#colors-and-links) |
An unknown option, a missing value, or an unsupported value returns exit code `2`.
## Select files
The CLI searches upward from the working directory for `stillwind.config.*`. In each
directory, it tries the extensions `ts`, `mts`, `cts`, `js`, `mjs`, `cjs`, and `json`
in that order. `--config` selects a file directly.
The CLI checks every file that `files` selects in each project, including files that
your application never imports. It can read other imported files for analysis, but
it does not change them.
Globs narrow this selection to some of these files. A glob is relative to each project
root, and it cannot add files outside `files`. You can pass several globs:
```sh
vp exec stillwind lint 'src/**/*.tsx' 'src/**/*.css'
```
A leading `./` is accepted. An absolute path selects that file when `files` includes
it. When nothing matches, the CLI returns exit code `2`.
## Saving files
`fmt` and `lint --fix` work out the changes for all selected files before they save
the first file. The CLI then saves only the files whose content changed, so
modification times of other files stay the same.
Outside edited ranges, UTF-8 BOMs, line endings, and trailing newlines stay intact.
Files must contain valid UTF-8.
When something fails:
- A file that cannot be read, analyzed, or rewritten stays unchanged. The CLI
continues with the other files, even after a saving failure.
- A file that changed while the CLI worked is rejected and stays as it is.
- A configuration or CSS failure affects every file that needs that configuration
or CSS.
- When projects overlap, every project that owns a file must produce the same final
text.
The CLI reports all failures and all saved files, and it returns exit code `2`.
## Exit codes
| Code | Meaning |
| ---- | ------------------------------------------------------------------------------------------------- |
| `0` | The command succeeded. `lint` may still report warnings when you set no `--max-warnings` limit |
| `1` | `fmt --check` found files to sort, `lint` found errors, or the warnings exceeded `--max-warnings` |
| `2` | The options were invalid, no files matched, or configuration, analysis, or file access failed |
Code `2` takes priority over code `1`.
## Output formats
| Format | Output |
| -------- | ------------------------------------------------------------------------------------- |
| `text` | Messages for reading in a terminal; the default outside GitHub Actions |
| `github` | Annotations that link findings to files; the default when `GITHUB_ACTIONS=true` |
| `json` | [One JSON object](#json-output) for scripts and AI agents |
| `files` | One path per line for each file that `fmt` changes or needs to change; only for `fmt` |
Results use stdout, and execution failures in `text` and `files` formats use stderr.
Configuration logs use stderr in every format. Only `text` output contains colors
and links.
### Positions and paths
`text` and `github` output count lines and columns from one. Columns count UTF-16
code units.
`text` paths are relative to the working directory. `github` paths are relative to
`GITHUB_WORKSPACE`, or to the working directory when that variable is not set.
A path on another filesystem volume stays absolute.
### Source excerpts
A finding at a source range shows a source excerpt, related locations, notes, and
suggestions. Excerpts show tabs as four spaces, and they align wide characters and
emoji. A long range shows its first four lines.
A finding about a whole document has no position or excerpt. The CLI also omits the
excerpt when it cannot read the source, or when the source changed after the
analysis.
## Colors and links
`--color` and `--hyperlinks` accept `auto`, `always`, and `never`. `always` and
`never` ignore the environment.
With `--color auto`, the CLI uses colors in terminals and supported CI logs. It
respects `NO_COLOR`, `FORCE_COLOR`, and `TERM=dumb`.
`--hyperlinks` controls OSC 8 links, which open local source files from the
terminal. With `auto`, the CLI uses them in recognized terminals, including VS Code
and Windows Terminal, and not in CI or redirected output. Terminals without OSC 8
support can still detect the printed `path:line:column` locations.
## JSON output
`--format json` prints one object with the same fields in every case, including
failures:
```json
{
"command": "lint",
"config": "/project/stillwind.config.ts",
"diagnostics": [],
"failures": [],
"changed": [],
"summary": {
"files": 1,
"errors": 0,
"warnings": 0,
"failures": 0,
"changed": 0,
"suggestions": 0,
"warningLimitExceeded": false
},
"exitCode": 0
}
```
| Field | Value |
| ------------- | ---------------------------------------------------------------------------------- |
| `command` | `"fmt"` or `"lint"`, or `null` when the CLI failed before it selected a command |
| `config` | The configuration path, or `null` when the CLI failed before the analysis |
| `diagnostics` | The findings; `--quiet` removes warnings from this list |
| `failures` | The execution failures |
| `changed` | The files that the command changed; with `--check`, the files that it would change |
| `summary` | Counts for the fields above; `warnings` includes warnings that `--quiet` hides |
| `exitCode` | The [exit code](#exit-codes) |
Each diagnostic contains `project`, a zero-based project index, and `report`. The
report contains the message, its locations, notes, and suggested edits.
Each failure contains `message` and `details`, and it can contain `project` and
`file`. `details` lists the dependency problems that caused the failure.
File paths are absolute. Locations in reports use URIs and zero-based UTF-16
positions, and their ends are exclusive.
# CSS ordering
> See how Stillwind orders CSS from different files, calls, conditions, variants, and utilities, and how the browser decides which value wins.
Source: https://stillwind.dev/docs/concepts/css-ordering · Markdown: https://stillwind.dev/docs/concepts/css-ordering/index.md
This page explains Stillwind's detailed CSS ordering rules for developers debugging
style conflicts or defining custom utilities and variants. It assumes you already
use [`style()`](/docs/guides/style) and [reusable styles](/docs/guides/reusable-styles),
and know how the CSS cascade works.
> **Prefer styles that do not depend on order**
>
> Avoid relying on which unrelated rule comes last to make your styles work.
> When rules do compete, Stillwind tries to put them in the order that authors
> are most likely to expect.
Stillwind chooses the order of generated CSS at build time. A later declaration
can override an earlier one. The browser can still prefer an earlier declaration
because of `!important`, cascade layers, or selector specificity.
## What affects CSS order
In `style(base, "bg-red-600")`, `base` is the result of another `style()` call.
The new call reuses its classes and adds CSS for the new utilities. Stillwind puts
the base's CSS first.
Read the following table from top to bottom. Stillwind orders files first, then
calls within each file, then the rules that each call produces:
| Step | What Stillwind orders | Which CSS comes first |
| ---- | ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 1 | Different files | A file that defines a base comes before a file that uses it in `style(base, ...)`. For files without this relationship, Stillwind uses a stable order based on their paths. |
| 2 | `style()` calls in one file | The base's CSS comes before CSS added by `style(base, ...)`. Other calls follow the order in which they appear in the file. |
| 3 | JavaScript conditions in one call | CSS without a JavaScript condition comes first. CSS for conditions follows in the order the conditions are written. If conditions are nested, CSS for the outer condition comes before CSS for the inner one. |
| 4 | CSS variants on one generated class | Rules without variants come first. The stylesheet sets the order of variants, such as `hover:` before `disabled:` or `sm:` before `md:` in the default stylesheet. |
| 5 | Utilities with the same variants | By default, utilities follow the order of their definitions in the stylesheet, regardless of their order in `style()`. |
For example, the variant order in step 4 only applies to rules for the same
class. It does not move a rule ahead of CSS from an earlier file or call.
The default `utilityOrder` setting is `"authored"`. In this mode, utilities from
plugins come before utilities defined in the stylesheet. Set `utilityOrder` to
`"tailwind"` to use Tailwind's property order instead. See
[Configuration](/docs/configuration#generated-css).
### A base's rules come before the new call's rules
Step 2 comes before step 3. All of the base's CSS comes first, including its
conditional rules. The new call's CSS follows, even if it has no condition:
### Source
```tsx
import { style } from "stillwind/react";
declare const active: boolean;
const base = style("bg-gray-100", active && "bg-blue-600");
export const danger = style(base, "bg-red-600");
```
### Compiled code
```ts
import { stillwindClassKey, stillwindClsx, stillwindMerge, stillwindToFragment } from "stillwind/runtime/class-name-object";
declare const active: boolean;
const base = {className:stillwindClsx("sw_fnaqw",(active) && ("sw_numny"))};
export const danger = stillwindMerge({[stillwindClassKey]:"sw_r65in"},stillwindToFragment((base)));
```
### Generated CSS
```css
.sw_fnaqw {
background-color: var(--color-gray-100);
}
.sw_numny {
background-color: var(--color-blue-600);
}
.sw_r65in {
background-color: var(--color-red-600);
}
```
The background is red whether `active` is true or false. All three selectors are
plain classes, and none of the declarations uses `!important`. The red rule wins
because it comes last. The same rule applies when you import `base` from another
file.
### Within one call, conditional rules come last
In this call, the red utility has a JavaScript condition and the blue utility
does not. Stillwind puts the blue rule first, even though it is written last:
```tsx
declare const active: boolean;
const props = style(active && "bg-red-600", "bg-blue-600");
```
When `active` is false, the element only has the class for blue. When `active`
is true, it also has the class for red, whose rule comes later. With several
conditions, a condition written later can override an earlier one when both
apply, unless specificity or `!important` decides otherwise.
### Within one class, the stylesheet orders variants
The built-in stylesheet defines the `hover` variant before the `disabled`
variant. Stillwind follows that definition order when it emits their CSS rules,
even when the hover utility is written last:
```tsx
const props = style("disabled:bg-gray-300 hover:bg-blue-600");
```
When the element is both hovered and disabled, the disabled background wins.
Both selectors have the same specificity, and the disabled rule comes last.
That variant order does not apply across separate calls. Here the new call's
hover rule follows the base's disabled rule:
```tsx
const base = style("disabled:bg-gray-300");
const props = style(base, "hover:bg-blue-600");
```
When both states match, the background is blue. The selectors still have the
same specificity, but the rule for the second call comes last.
## What does not affect CSS order
| What you change | What happens |
| ------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------- |
| Reorder utility strings that have no JavaScript condition | Stillwind uses the configured utility order. Splitting a string into arguments does not make the last argument win. |
| Reorder existing bases in `style(first, second)` | The last argument does not become the winning base. Stillwind orders the calls that defined those bases using steps 1 and 2 above. |
| Reorder class names on an element | The browser uses the order of declarations in the stylesheet, regardless of the class attribute's order. |
| Change JavaScript import order, component render order, or which stylesheet finishes downloading first | For the same set of files, the integration keeps the same CSS order. |
For example, with the default stylesheet, both calls below produce the same
padding declarations, and `p-4` wins:
```tsx
style("p-2 p-4");
style("p-4", "p-2");
```
[conflicting-utilities](/docs/lints/conflicting-utilities) reports this
conflict. Remove the unwanted utility instead of rearranging the input.
If two base styles set the same property, do not use their argument order to
choose the winner. Define the overriding style by passing the other style as
its base:
```tsx
const blue = style("bg-blue-600");
const red = style(blue, "bg-red-600");
const props = style(red);
```
[ambiguous-style-base-order](/docs/lints/ambiguous-style-base-order) and
[interfering-imported-style-base](/docs/lints/interfering-imported-style-base)
report calls that combine conflicting bases without saying which is built on
which.
## Specificity and `!important`
Putting a rule later does not make its selector more specific. For example,
a base's class with `:hover` is more specific than the new call's plain class:
### Source
```tsx
import { style } from "stillwind/react";
const base = style("bg-blue-600 hover:bg-blue-800");
export const danger = style(base, "bg-red-600");
```
### Compiled code
```ts
import { stillwindClassKey, stillwindMerge, stillwindToFragment } from "stillwind/runtime/class-name-object";
const base = {className:"sw_221vg"};
export const danger = stillwindMerge({[stillwindClassKey]:"sw_crw5t"},stillwindToFragment((base)));
```
### Generated CSS
```css
.sw_221vg {
background-color: var(--color-blue-600);
}
@media (hover: hover) {
.sw_221vg:hover {
background-color: var(--color-blue-800);
}
}
.sw_crw5t {
background-color: var(--color-red-600);
}
```
The background is red at rest. On a device that supports hover, it becomes
blue-800 while hovered: the earlier class with `:hover` beats the later plain
class. To make the hovered background red too, give the new call its own hover
rule:
```tsx
export const danger = style(base, "bg-red-600 hover:bg-red-800");
```
A declaration with `!important` beats a normal declaration, even if the normal
one has a more specific selector. Here the base's blue background wins both at
rest and on hover, despite the red rules coming later:
```tsx
const base = style("bg-blue-600!");
const danger = style(base, "bg-red-600 hover:bg-red-800");
```
Layer order also comes before specificity. Among layers, the last layer wins
for normal declarations, and the first layer wins for important declarations.
The browser uses declaration order only when the earlier rules of the
[CSS cascade](https://www.w3.org/TR/css-cascade-5/#cascade-sort) leave a tie.
To override a shared style, use `style(base, ...)` with the matching variants
instead of adding `!important`. See [no-important](/docs/lints/no-important).
## Stylesheet placement
The integration keeps this order during development, in production, and in
server-rendered pages. A production build may combine or move CSS rules when
doing so does not change which declaration wins.
If you combine CSS from separate builds, or place the CSS strings returned by
[`style.css()`](/docs/macros/css) yourself, you choose which stylesheet comes
first.
# How styles compile
> See what Stillwind generates at build time, what JavaScript remains at runtime, and how CSS reaches the page.
Source: https://stillwind.dev/docs/concepts/how-styles-compile · Markdown: https://stillwind.dev/docs/concepts/how-styles-compile/index.md
Stillwind compiles `style()` calls when your bundler builds the application.
This page shows what the compiler generates, what JavaScript remains at
runtime, and how the CSS reaches the page.
## Static styles
A call with only static utilities and CSS variants compiles to an object literal:
### Source
```tsx
import { style } from "stillwind/react";
export const props = style("rounded-md p-4 text-blue-600 hover:text-blue-800 md:p-6");
```
### Compiled code
```ts
export const props = {className:"sw_hk649"};
```
### Generated CSS
```css
.sw_hk649 {
padding: calc(var(--spacing) * 4);
color: var(--color-blue-600);
border-radius: var(--radius-md);
}
@media (hover: hover) {
.sw_hk649:hover {
color: var(--color-blue-800);
}
}
@media (width >= 48rem) {
.sw_hk649 {
padding: calc(var(--spacing) * 6);
}
}
```
In this example, the utilities compile to one class. The browser applies
`hover:` through a selector and `md:` through a media query. Both stay in CSS,
so the compiled JavaScript contains only the class name.
## Conditions and runtime values
A condition or a runtime value needs a small amount of JavaScript:
### Source
```tsx
import { style } from "stillwind/react";
declare const active: boolean;
declare const progress: number;
export const props = style("p-4", active && "bg-blue-500", { "--progress": progress });
```
### Compiled code
```ts
import { stillwindClsx, stillwindCssValue } from "stillwind/runtime/class-name-object";
declare const active: boolean;
declare const progress: number;
export const props = {className:stillwindClsx("sw_zwy1n",(active) && ("sw_h7hj9")),style:{"--progress":stillwindCssValue(progress)}};
```
### Generated CSS
```css
.sw_zwy1n {
padding: calc(var(--spacing) * 4);
}
.sw_h7hj9 {
background-color: var(--color-blue-500);
}
```
The compiled call imports helpers to join the class names and pass the runtime
custom property as an inline style.
The CSS for both classes is generated at build time. At runtime, the code only
chooses class names and sets property values.
| You write | JavaScript at runtime |
| -------------------------------------- | ------------------------------------------- |
| Static utilities and variants | A class name |
| A condition, such as `active && "..."` | A helper that joins class names |
| A runtime custom property | An inline `style` value |
| `style.cva()` | A factory that selects compiled class names |
| `style.media()` | A string with the media query |
| [`style.css()`](/docs/macros/css) | A CSS string that you place yourself |
Development builds import checked versions of the helpers from
`stillwind/runtime/class-name-object-development`. These versions report invalid values
while you develop. Production builds use the unchecked helpers.
## The generated stylesheet
The stylesheet contains utility CSS only for the `style()` calls that the build
compiles. Utilities that no compiled call uses produce no CSS.
Stillwind fixes the precedence of its generated rules at build time. Class-name
order and module-loading order do not change it. Production optimizations can
combine or move rules without changing the cascade. See
[CSS ordering](/docs/concepts/css-ordering) for base styles, conditions, and variants.
## Delivering CSS to the page
The build integration adds the generated CSS to your application. For Vite and
the frameworks built on it, the build writes one stylesheet by default.
The Astro integration also adds the styles to server-rendered pages and islands.
SvelteKit needs a server hook to add them to server-rendered pages in development.
See [Framework integrations](/docs/integrations) for the setup of each framework.
`style.css()` returns its CSS as a string instead of adding it to this stylesheet.
To add the styles of a module to a shadow root, see [Web Components](/docs/guides/web-components).
# Stylesheets
> See which CSS files the stillwind package provides, how to import them separately, and which optional files change built-in utilities.
Source: https://stillwind.dev/docs/concepts/stylesheets · Markdown: https://stillwind.dev/docs/concepts/stylesheets/index.md
Most projects need one line:
```css
@import "stillwind";
```
This page lists the CSS files behind that import. Read it when you leave out part
of the default stylesheet or add an optional file.
## Stylesheets of the package
| Import | Content |
| ------------------------- | -------------------------------------------------------- |
| `stillwind` | All of the files below except the optional ones |
| `stillwind/theme.css` | Theme tokens |
| `stillwind/preflight.css` | The reset of default element styles |
| `stillwind/utilities.css` | The slot where compiled utility rules go |
| `stillwind/builtins.css` | Built-in utilities and variants |
| `stillwind/templates.css` | Output templates of `style.css()` |
| `stillwind/logical/*.css` | Optional: logical properties for built-in axis utilities |
## Import the files separately
`@import "stillwind"` has the same effect as these lines:
```css
@layer properties, theme, base, components, utilities;
@import "stillwind/theme.css" layer(theme);
@import "stillwind/preflight.css" layer(base);
@import "stillwind/utilities.css" layer(utilities);
@import "stillwind/builtins.css";
@import "stillwind/templates.css";
```
Write the `@layer` statement and keep the `layer()` assignments when you remove a
line. They decide how these files compete with the rest of your CSS. For example,
[Migrating from CSS](/docs/guides/migrating-from-css) leaves out `preflight.css`
until the old styles are gone.
## Optional stylesheets
An optional stylesheet changes built-in utilities, so `stillwind` does not include
it. The default definitions stay compatible with Tailwind CSS.
Import an optional stylesheet after `stillwind` or `stillwind/builtins.css`. It
replaces only the definitions that come before it:
```css
@import "stillwind";
@import "stillwind/logical/overflow.css";
```
### Logical axis utilities
The files in `stillwind/logical/` make built-in axis utilities follow the writing
direction, as `px-*` and `py-*` do. Your class names stay the same, and each file
changes only its own utilities. Import the files that you need:
| File | Utility | Without the file | With the file |
| ---------------- | ---------------- | --------------------------------- | -------------------------------------------- |
| `overflow.css` | `overflow-x-*` | `overflow-x` | `overflow-inline` |
| `overflow.css` | `overflow-y-*` | `overflow-y` | `overflow-block` |
| `overscroll.css` | `overscroll-x-*` | `overscroll-behavior-x` | `overscroll-behavior-inline` |
| `overscroll.css` | `overscroll-y-*` | `overscroll-behavior-y` | `overscroll-behavior-block` |
| `divide.css` | `divide-y-*` | `border-top-*`, `border-bottom-*` | `border-block-start-*`, `border-block-end-*` |
| `snap.css` | `snap-x` | `scroll-snap-type: x` | `scroll-snap-type: inline` |
| `snap.css` | `snap-y` | `scroll-snap-type: y` | `scroll-snap-type: block` |
| `resize.css` | `resize-x` | `resize: horizontal` | `resize: inline` |
| `resize.css` | `resize-y` | `resize: vertical` | `resize: block` |
In a horizontal writing mode, the result is the same. In a vertical writing mode,
the utilities change axes, so `overflow-x-auto` scrolls vertically.
[prefer-logical-properties](/docs/lints/prefer-logical-properties) does not report
the `overflow`, `overscroll`, and `divide` utilities after you import their files.
It still reports arbitrary properties such as `[overflow-x:auto]`, because these
files do not change them. Their logical forms, such as `[overflow-inline:auto]`,
are available.
The utilities keep their cascade order, so `overflow-x-auto` still overrides
`overflow-hidden`.
# Configuration
> Set up projects in stillwind.config.ts, choose lint rules, and look up every project field.
Source: https://stillwind.dev/docs/configuration · Markdown: https://stillwind.dev/docs/configuration/index.md
`stillwind.config.ts` describes your projects. The build integration, the CLI,
and the editor all read the same file.
```ts title="stillwind.config.ts"
import { defineConfig } from "stillwind/config";
export default defineConfig({
projects: [
{
css: "./src/stillwind.css",
files: ["src/**/*.{ts,tsx,vue,svelte,astro}"],
},
],
});
```
Each entry in `projects` selects a stylesheet and the files that belong to it.
Most applications need one project. A monorepo can list one project for each
application, or keep a configuration file in each package and reference those
files.
## Reference other configuration files
A string in `projects` references other configuration files, relative to the
file that declares it. Strings and project objects can appear in the same list.
```ts title="stillwind.config.ts"
import { defineConfig } from "stillwind/config";
export default defineConfig({
projects: ["apps/*", "!apps/legacy", "packages/ui", "tools/site.stillwind.ts"],
});
```
| Entry | Selects |
| ------------------------- | ------------------------------------------------------------------------ |
| `tools/site.stillwind.ts` | That configuration file, with any name |
| `packages/ui` | The `stillwind.config.*` file in that directory |
| `apps/*` | `stillwind.config.*` files that the glob matches or finds in directories |
| `!apps/legacy` | Removes a path or a glob from the matches of glob entries |
A path or a directory that is missing causes an error. A glob skips directories
that have no configuration file, and it does not search `node_modules` or `.git`.
Stillwind reports an error only when no project remains in the list.
A relative `root` in a referenced file uses the directory of that file, so
packages keep working on their own. Referenced files must list project objects
because references do not nest. Project names must be unique across all files.
Build tools watch the referenced files, but they do not notice a new file that a
glob would match. Restart the build after you add a package.
## Where Stillwind finds the file
The build integration searches from the application root upward. The CLI and
the editor search from the working directory or the workspace upward. The file
in the nearest directory wins.
The editor also searches from each file that you open. A monorepo therefore
works without a configuration file at its root: when no open project includes
the file, the editor uses the nearest configuration file inside the workspace.
Setting an explicit configuration file turns this search off.
Stillwind accepts `stillwind.config.ts`, `.mts`, `.cts`, `.js`, `.mjs`, `.cjs`,
and `.json`. In one directory, it uses the first of these that exists.
`defineConfig()` also accepts a function or an async function that returns the
settings. Stillwind calls it once and uses the result.
## Project fields
### Required
| Field | Value |
| ------- | ---------------------------------------------------------------------------------- |
| `css` | Path to the stylesheet that defines the theme, utilities, and variants |
| `files` | Globs for the files that the CLI and the editor check; the build does not use them |
### Scope
| Field | Value |
| ---------- | ------------------------------------------------------------------------------------ |
| `name` | A unique name that selects this project from an integration or the CLI |
| `root` | The project directory, relative to the configuration file; defaults to its directory |
| `exclude` | Globs that remove files from `files`; `node_modules` and `.git` are always excluded |
| `tsconfig` | Path to the TypeScript configuration; defaults to `tsconfig.json` in the root |
Paths in `css`, `files`, `exclude`, and `tsconfig` are relative to `root`.
### Checks and sorting
| Field | Value |
| ------ | ------------------------------------------------------------------------------------------ |
| `lint` | Presets and rules; see [Lint](#lint) |
| `sort` | Where `stillwind fmt` sorts utilities, or `false` to disable them; see [Sorting](#sorting) |
### Generated CSS
| Field | Value |
| -------------- | --------------------------------------------------------------------------------------------------------------------------- |
| `target` | Minimum browser versions, such as `["chrome111", "safari17"]`; removes fallbacks they do not need |
| `utilityOrder` | `"authored"` orders utilities as your stylesheet defines them; `"tailwind"` orders them as Tailwind does |
| `important` | `true` makes every utility `!important`; a selector nests utilities under that selector |
| `tailwind` | A Tailwind configuration object; see [Migrating from Tailwind CSS](/docs/guides/migrating-from-tailwind#move-configuration) |
| `plugins` | Plugin objects for the `@plugin` rules of your stylesheet |
| `rootFontSize` | Pixels per `rem`, used by lint fixes and editor previews; defaults to 16 |
| `useCssIf` | `true` lets runtime CSS conditions use the native CSS `if()` function; defaults to `false` |
### Generated names
| Field | Value |
| ---------------- | ----------------------------------------------------------------------------------- |
| `classNamespace` | Text added to generated class names; use the same value in client and server builds |
| `hashLength` | Number of hash characters in generated names, from 1 to 50; defaults to 5 |
| `prefix` | Prefix for Stillwind's custom properties; defaults to `--sw-` |
| `tailwindPrefix` | Prefix for Tailwind-compatible internal custom properties; defaults to `--tw-` |
| `themePrefix` | Prefix for theme variables in generated CSS, such as `--tw-`; omit it to keep names |
| `naming` | Functions that choose generated names yourself |
| `namingRevision` | A string that you change whenever you change the `naming` functions |
### Editor
| Field | Value |
| --------- | --------------------------------------------------------------------------------------------------------------------- |
| `preview` | Which comments [CSS previews](/docs/editors#settings) show: `themeValues`, `pixelEquivalents`, and `colorEquivalents` |
The [shared configuration API](https://github.com/SegaraRai/stillwind/blob/main/packages/config/src/compiler.ts)
describes the remaining fields for custom integrations, such as `sources`,
`projection`, `typeFacts`, and `automatic`.
## Lint
The `lint` field of a project selects the rules that the CLI and the editor
report. [Checks in the editor and CI](/docs/guides/lint-adoption) explains
where the rules run.
### Presets and severities
```ts title="stillwind.config.ts"
import { defineConfig, lintPresets } from "stillwind/config";
export default defineConfig({
projects: [
{
css: "./src/stillwind.css",
files: ["src/**/*.{ts,tsx,vue,svelte,astro}"],
lint: {
extends: [lintPresets.recommended, lintPresets.stylistic],
rules: {
"unknown-utility": "deny",
"no-arbitrary-colors": "warn",
},
},
},
],
});
```
| Preset | Contents |
| ------------- | ---------------------------------------------------------------------- |
| `recommended` | Invalid input, conflicting styles, and other likely mistakes |
| `strict` | Every `recommended` rule as an error, and unused suppression comments |
| `stylistic` | Preferred spellings and utility sorting; combine it with `recommended` |
The [lint rule reference](/docs/lints) shows the severity of each rule in
`recommended`. Each rule page shows its severity in every preset.
Each rule has one of three severities:
| Severity | Effect |
| -------- | --------------------------------------------------------- |
| `warn` | Reports a warning, which does not fail the CLI by default |
| `deny` | Reports an error, which fails the CLI |
| `off` | Reports nothing and applies no fixes |
### How the settings combine
| `lint` value | Result |
| --------------------------- | ------------------------------------ |
| Not set | The `recommended` preset |
| An object without `extends` | No preset; only the rules in `rules` |
| `false` or `{}` | No rules and no fixes |
Stillwind applies the presets in `extends` in order, and then `rules`. A later
setting replaces the severity of an earlier one. Options in objects merge, and
arrays replace earlier arrays. A severity alone, such as `"deny"`, keeps the
rule's options from the presets.
An unknown rule name is a configuration error. Turning off rules does not turn
off [compiler errors](/docs/errors).
### Rule options
Some rules accept options. Write the rule as an object with `severity` and the
options:
```ts
const rules = {
"no-restricted-utilities": {
severity: "deny",
utilities: [{ pattern: "absolute", message: "Use the positioned component." }],
},
"no-restricted-declarations": {
severity: "deny",
rules: [{ properties: ["position"], values: ["absolute"] }],
},
"no-restricted-length-units": {
severity: "warn",
rules: [{ properties: ["width", "height"], disallow: ["px"] }],
},
"no-restricted-theme-tokens": {
severity: "deny",
tokens: ["--color-blue-*"],
},
};
```
| Rule | Options |
| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `conflicting-utilities` | `allowShorthandOverrides`: allows the supported overrides between shorthand and longhand utilities; defaults to `false` |
| `invalid-marker-use` | `ignoredClasses`: marker class names that the rule ignores |
| `no-arbitrary-spacing` | `properties`: properties to check in addition to margin, padding, and gap |
| `no-restricted-utilities` | `utilities`: utility patterns, each with an optional message |
| `no-restricted-declarations` | `rules`: patterns for properties and values; every matching entry applies |
| `no-restricted-length-units` | `rules`: property patterns and the units to `disallow`; the last matching entry applies |
| `no-restricted-theme-tokens` | `tokens`: patterns for theme custom properties; required when the rule is on |
| `prefer-canonical-utilities` | `pxToRem` and `collapse` default to `true`; `logicalToPhysical` defaults to `false`; `preserveSpecificity` defaults to `true`. See the [rule options](/docs/lints/prefer-canonical-utilities#options). |
| `prefer-variant-directive` | `pxToRem`: treats `px` and `rem` in media queries as equal at 16px per `rem`; defaults to `false` |
Patterns accept `*` for any text and `?` for one character. Utility and theme
token patterns are case-sensitive. Property and value patterns are not.
### Definitions of packages and plugins
[incompatible-property-value](/docs/lints/incompatible-property-value) checks
the declarations that utility definitions write. By default, it checks only your
own definitions: your stylesheet, the stylesheets that it imports by a relative
or absolute path, and the plugin files that it loads by path. Two project-level
fields of `lint` add the definitions of packages and plugins. Presets cannot set
them.
```ts
lint: {
extends: [lintPresets.recommended],
checkLibraries: ["@acme/*"],
checkPlugins: ["brand"],
}
```
| Field | Checks the definitions of |
| ---------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| `checkLibraries` | Stylesheets that you import by package name, and stylesheets under `node_modules`, matched by package name, such as `stillwind` |
| `checkPlugins` | Plugins that you load by package name or configure in `plugins`, matched by the name in the `@plugin` rule |
Each field accepts `true` for every package or plugin, `false` for none, or a
list of case-sensitive patterns. Both fields default to `false`. Use them to
check a package of your own, such as a design system in the same repository, or
to find problems to report upstream.
## Suppression comments
To allow one exception, add a comment that names the rule. Give the reason after
`--`:
```ts
import { style } from "stillwind/react";
// swlint-disable-next-line no-arbitrary-colors -- External brand color.
export const badge = style("bg-[#123456]");
```
| Comment | Applies to |
| ------------------------------------------------ | ---------------------------------- |
| `swlint-disable-next-line ` | The next line |
| `swlint-disable-line ` | The same line |
| `swlint-disable ` … `swlint-enable ` | The lines between the two comments |
In stylesheets, write the same text in `/* ... */` comments.
A comment hides the finding only. A misspelled utility still produces no CSS.
[invalid-lint-suppression](/docs/lints/invalid-lint-suppression) reports a
malformed comment, and
[unused-lint-suppression](/docs/lints/unused-lint-suppression) reports a
comment that suppresses nothing.
## Sorting
The `sort` field controls where `stillwind fmt`, the editor, and the
[Prettier plugin](/docs/formatters#prettier) sort utilities:
| Option | Sorts | Default |
| ----------------- | -------------------------------------------------- | ------- |
| `stringLiterals` | Utilities inside each string | `true` |
| `arrays` | Arguments, array items, and object entries by kind | `true` |
| `applyUtilities` | Utilities inside each `@apply` rule | `true` |
| `applyStatements` | Adjacent `@apply` rules | `false` |
| `variantBlocks` | Adjacent `@variant` blocks | `false` |
`sort: false` disables sorting, including `stillwind fmt` and the
[prefer-sorted-utilities](/docs/lints/prefer-sorted-utilities) rule. Turning off
only that rule keeps `stillwind fmt` working.
The CLI checks the files that `files` selects. File patterns on the command line
narrow that set; they cannot add files outside it.
## Several projects
When the file has several projects, each integration selects one:
1. If the integration has a `project` option, it selects the project with that `name`.
2. Otherwise, it selects the project whose `root` is the deepest directory that
contains the application root.
If no project or more than one project matches, the build fails with a
configuration error. The CLI and the editor check every project.
## Override settings in the integration
The integration accepts options that change how it reads the file:
```ts
import { stillwind } from "@stillwind/integration/vite";
stillwind({ configFile: "config/stillwind.config.ts", project: "web" });
```
`configFile` selects another file, relative to the application root. Other
options, such as `css` or `lint`, replace the values of the selected project.
Objects merge with the file's values, and arrays replace them.
# Editors
> Install the Stillwind extension, sort and fix on save, and connect other editors to the language server.
Source: https://stillwind.dev/docs/editors · Markdown: https://stillwind.dev/docs/editors/index.md
The Stillwind language server shows diagnostics, generated CSS, and completion
from the active design system while you edit. It reads the same
`stillwind.config.ts` as the CLI and the build, and it checks unsaved files too.
Create that file with [Getting started](/docs) first.
## VS Code
Install **Stillwind** from the
[Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=stillwind.stillwind)
or [Open VSX](https://open-vsx.org/extension/stillwind/stillwind). An editor that
installs extensions from Open VSX uses the same package.
The extension needs a trusted workspace, because it runs your project
configuration as JavaScript.
### Features
- Hover over utilities, `style()` calls, or bound variables to see the generated CSS.
- Complete utilities, variants, and theme values.
- Complete quoted `@plugin` paths, and follow links to their modules.
- See colors, and open color pickers in utilities and theme references.
- Apply compiler Quick Fixes.
- Run **Stillwind: Sort Utilities**.
Stylesheets have completion for Stillwind at-rules, and VS Code's CSS service does
not report these at-rules as unknown.
### Language server version
Desktop VS Code runs the `@stillwind/cli` version that the workspace installs, so
editor diagnostics match the compiler of that version. Install
[the CLI](/docs/cli) in the project to get this match.
The extension uses its bundled language server when the workspace has no CLI, or
when the CLI fails to start. The **Stillwind** output channel shows which server
is running.
### Settings
| Setting | Value |
| ----------------------------------------- | ---------------------------------------------------------------------------------------------- |
| `stillwind.configFile` | A configuration path relative to the workspace root; empty searches for `stillwind.config.*` |
| `stillwind.completion.registryDirectives` | `true` suggests [registry directives](/docs/at-rules/registry-directives) in utility libraries |
Run **Stillwind: Restart Language Server** to reload configuration and dependencies.
The `preview` field of each project in `stillwind.config.ts` controls the comments
after values in CSS previews:
| Option | Comment |
| ------------------ | ------------------------------------------------------------ |
| `themeValues` | Resolved theme values and evaluated `calc()` results |
| `pixelEquivalents` | Pixel values for `rem` |
| `colorEquivalents` | Hexadecimal sRGB colors; `"exact"` omits colors outside sRGB |
All three are enabled by default. With the default `colorEquivalents` value,
`"approximate"`, a `≈` marks colors that the preview maps into sRGB. `false` turns
off an option.
### Sort and fix on save
Use a [document formatter](/docs/formatters) for layout and whitespace, and add
Stillwind's Code Actions:
```json
{
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll.stillwind": "explicit",
"source.sort.stillwind": "explicit"
}
}
```
`source.fixAll.stillwind` applies the enabled lint fixes and respects suppression
comments. `source.sort.stillwind` sorts whatever the lint severity is.
`lint: false` in the project disables lint rules and fixes. `sort: false` also
disables explicit sorting commands. The
[`sort` field](/docs/configuration#sorting) selects what the editor sorts.
### Web VS Code
The Web extension always uses the bundled language server, and it needs a host with
cross-origin isolation. These limits apply:
- Project configuration can import browser-compatible modules. Node built-ins are
not available.
- The workspace filesystem must be able to read the dependencies.
- The default browser provider supports JS, JSX, TS, and TSX. Vue, Svelte, and
Astro files need a custom source or projection provider.
## Other editors
An editor with a Language Server Protocol client can start the language server from
the CLI. Install [the CLI](/docs/cli) in the project, and run this command in the
workspace:
```sh
stillwind lsp --stdio
```
The server discovers the configuration from each workspace folder.
# Compiler error reference
> Find a compiler error by its code, and see whether to fix the source, fix the configuration, or report a bug.
Source: https://stillwind.dev/docs/errors · Markdown: https://stillwind.dev/docs/errors/index.md
A compiler error stops the compilation of a module. Unlike a lint finding, you
cannot turn it off or suppress it with a comment. Each error page explains what
causes the error and how to fix it.
The first digits of a code tell you what to do next:
| Codes | What to do |
| ----------------- | ---------------------------------------------------- |
| SW01xxx – SW03xxx | Fix `stillwind.config.ts` or the integration options |
| SW10xxx – SW15xxx | Fix your components, `style()` calls, or stylesheet |
| SW30xxx – SW34xxx | Check your integration, or report a bug |
| SW90xxx | Report a bug |
## Fix the configuration
- [SW01001](/docs/errors/SW01001): Invalid property prefix
- [SW01002](/docs/errors/SW01002): Invalid hash length
- [SW01003](/docs/errors/SW01003): Invalid lint configuration
- [SW02001](/docs/errors/SW02001): Framework constraint conflict
- [SW02002](/docs/errors/SW02002): Unresolved root stylesheet
- [SW03001](/docs/errors/SW03001): Generated identifier collision
- [SW03002](/docs/errors/SW03002): Identifier generator failed
- [SW03003](/docs/errors/SW03003): Theme variable collision
## Fix your components and style() calls
- [SW10001](/docs/errors/SW10001): JavaScript parse error
- [SW10002](/docs/errors/SW10002): Invalid component syntax
- [SW10003](/docs/errors/SW10003): Invalid Unicode string
- [SW10004](/docs/errors/SW10004): Unconsumed macro use
- [SW10005](/docs/errors/SW10005): Untransformed macro reference
- [SW11001](/docs/errors/SW11001): Style composition cycle
- [SW11002](/docs/errors/SW11002): CSS module ordering cycle
- [SW11003](/docs/errors/SW11003): Unavailable style base
- [SW12001](/docs/errors/SW12001): Incompatible declaration assignment
- [SW12002](/docs/errors/SW12002): Declaration identities unavailable
## Fix your stylesheet
- [SW13001](/docs/errors/SW13001): Authored CSS parse error
- [SW13002](/docs/errors/SW13002): Unterminated CSS block
- [SW13003](/docs/errors/SW13003): Invalid CSS block
- [SW13004](/docs/errors/SW13004): CSS nesting limit exceeded
- [SW14001](/docs/errors/SW14001): Missing utilities slot
- [SW14002](/docs/errors/SW14002): Missing support slot
- [SW14003](/docs/errors/SW14003): Malformed property requirement
- [SW14004](/docs/errors/SW14004): Malformed utility property requirement
- [SW14005](/docs/errors/SW14005): Required property is unregistered
- [SW14006](/docs/errors/SW14006): Property-usage parse failure
- [SW14007](/docs/errors/SW14007): Malformed theme reference
- [SW14008](/docs/errors/SW14008): Circular utility application
- [SW15001](/docs/errors/SW15001): CSS offset exceeds source coordinates
- [SW15002](/docs/errors/SW15002): Rendered source is too large
- [SW15003](/docs/errors/SW15003): Source size or offset is too large
## Check your integration
These errors come from the connection between the compiler and the build tool
or the editor. With an official integration, update the Stillwind packages
first. If the error remains, report it as a bug. If you write your own
integration, the error page explains which input to fix.
### Type information
- [SW30001](/docs/errors/SW30001): TypeScript checker facts required
- [SW30002](/docs/errors/SW30002): Invalid or stale TypeScript facts
- [SW30003](/docs/errors/SW30003): Incompatible symbolic fact kinds
- [SW30004](/docs/errors/SW30004): Checker expression unavailable
### Vue, Svelte, and Astro components
- [SW31001](/docs/errors/SW31001): Invalid projection map
- [SW31002](/docs/errors/SW31002): Ambiguous or missing original range
- [SW31003](/docs/errors/SW31003): Projection content mismatch
- [SW31004](/docs/errors/SW31004): Invalid converter output syntax
- [SW31005](/docs/errors/SW31005): Component projection preparation failed
- [SW31006](/docs/errors/SW31006): Invalid UTF-16 offset
- [SW31007](/docs/errors/SW31007): Invalid UTF-16 position
- [SW31008](/docs/errors/SW31008): Invalid UTF-8 offset
- [SW31009](/docs/errors/SW31009): Unmapped macro binding read
- [SW31010](/docs/errors/SW31010): Edit outside an editable projection region
- [SW31011](/docs/errors/SW31011): Attribute quote mismatch
### Stylesheet loading and source files
- [SW32001](/docs/errors/SW32001): CSS imports need host resolution
- [SW32002](/docs/errors/SW32002): Invalid initial CSS batch
- [SW32003](/docs/errors/SW32003): Unknown or duplicate CSS request
- [SW32004](/docs/errors/SW32004): Conflicting CSS source
- [SW32005](/docs/errors/SW32005): CSS loader already completed
- [SW32006](/docs/errors/SW32006): CSS request IDs exhausted
- [SW32007](/docs/errors/SW32007): CSS source IDs exhausted
- [SW33001](/docs/errors/SW33001): Original map on an internal source
- [SW33002](/docs/errors/SW33002): Invalid source byte range
- [SW33003](/docs/errors/SW33003): Span belongs to another file
- [SW33004](/docs/errors/SW33004): Invalid source span
- [SW33005](/docs/errors/SW33005): Invalid source byte offset
### Code transformation
- [SW34001](/docs/errors/SW34001): Missing macro import anchor
- [SW34002](/docs/errors/SW34002): Missing module CSS target
- [SW34003](/docs/errors/SW34003): Transform requested after failed compilation
## Report a bug
These errors mean that the compiler produced an inconsistent result. Please
[open an issue](https://github.com/SegaraRai/stillwind/issues) with the error
message and, if possible, the source that causes it.
- [SW90001](/docs/errors/SW90001): Invalid generated CSS block
- [SW90002](/docs/errors/SW90002): Missing retained rule
- [SW90003](/docs/errors/SW90003): Inconsistent internal CSS graph
- [SW90004](/docs/errors/SW90004): Inconsistent macro import metadata
- [SW90005](/docs/errors/SW90005): Macro anchor removal edit missing
- [SW90006](/docs/errors/SW90006): Invalid transform expression mapping
- [SW90007](/docs/errors/SW90007): Overlapping source replacements
- [SW90008](/docs/errors/SW90008): Invalid compiler-produced source coordinates
# SW01001: Invalid property prefix
> The prefix, tailwindPrefix, or themePrefix setting does not start with -- and end with -.
Source: https://stillwind.dev/docs/errors/SW01001 · Markdown: https://stillwind.dev/docs/errors/SW01001/index.md
This error occurs when `prefix`, `tailwindPrefix`, or `themePrefix` is not a valid prefix for
custom properties. A prefix must start with `--`, end with `-`, and contain no
whitespace. The message names the setting.
## Reported
**stillwind.config.ts**
```ts
import { defineConfig } from "stillwind/config";
export default defineConfig({
projects: [
{
css: "./src/stillwind.css",
files: ["src/**/*.tsx"],
prefix: "sw",
},
],
});
```
> SW01001: prefix must start with `--` and end with `-`
## Fixed
```ts title="stillwind.config.ts"
import { defineConfig } from "stillwind/config";
export default defineConfig({
projects: [
{
css: "./src/stillwind.css",
files: ["src/**/*.tsx"],
prefix: "--sw-",
},
],
});
```
## How to fix
- Add `--` at the start and `-` at the end, as in the example.
- Use the same value in client and server builds that share styles.
# SW01002: Invalid hash length
> The hashLength setting is outside the supported range.
Source: https://stillwind.dev/docs/errors/SW01002 · Markdown: https://stillwind.dev/docs/errors/SW01002/index.md
This error occurs when `hashLength` is not an integer from 1 to 50. The setting
chooses the number of hash characters in generated names. The message shows the
value and the maximum.
## Reported
**stillwind.config.ts**
```ts
import { defineConfig } from "stillwind/config";
export default defineConfig({
projects: [
{
css: "./src/stillwind.css",
files: ["src/**/*.tsx"],
hashLength: 0,
},
],
});
```
> SW01002: hashLength must be between 1 and 50 base-36 digits, not 0
## Fixed
```ts title="stillwind.config.ts"
import { defineConfig } from "stillwind/config";
export default defineConfig({
projects: [
{
css: "./src/stillwind.css",
files: ["src/**/*.tsx"],
hashLength: 5,
},
],
});
```
## How to fix
- Use an integer from 1 to 50. The default is 5.
- To shorten names, lower the value. To make collisions less likely, raise it.
- Use the same value in client and server builds that share styles.
# SW01003: Invalid lint configuration
> A lint rule has an option value that the compiler cannot use.
Source: https://stillwind.dev/docs/errors/SW01003 · Markdown: https://stillwind.dev/docs/errors/SW01003/index.md
This error occurs when a lint rule has an option value that the compiler cannot
use, such as an unknown unit or an empty list that the rule requires. The message
names the rule and the value.
## Reported
**stillwind.config.ts**
```ts
import { defineConfig } from "stillwind/config";
export default defineConfig({
projects: [
{
css: "./src/stillwind.css",
files: ["src/**/*.tsx"],
lint: {
rules: {
"no-restricted-length-units": {
severity: "warn",
rules: [{ properties: ["width"], disallow: ["pixels"] }],
},
},
},
},
],
});
```
> SW01003: invalid `no-restricted-length-units` lint configuration: rules require property patterns and valid CSS length units
## Fixed
```ts title="stillwind.config.ts"
import { defineConfig } from "stillwind/config";
export default defineConfig({
projects: [
{
css: "./src/stillwind.css",
files: ["src/**/*.tsx"],
lint: {
rules: {
"no-restricted-length-units": {
severity: "warn",
rules: [{ properties: ["width"], disallow: ["px"] }],
},
},
},
},
],
});
```
## How to fix
- Correct the value named in the message. In the example, the unit is `px`, not
`pixels`.
- Give the rules that need a list, such as `no-restricted-theme-tokens`, at least
one entry.
Each [lint rule page](/docs/lints) describes its options.
# SW02001: Framework constraint conflict
> The prepared source selects a framework that differs from the component format.
Source: https://stillwind.dev/docs/errors/SW02001 · Markdown: https://stillwind.dev/docs/errors/SW02001/index.md
This error occurs when a custom integration supplies a source `framework` that
conflicts with the component's original format. For example, a Vue component
cannot be projected with an explicit Svelte framework constraint.
## How to fix
Set the prepared source's `framework` field to the component's framework, or omit
it when the integration does not need a source constraint. The converter must also
match the component format.
Macro imports select each call's output format independently. A file can import
several framework macros, including React and vanilla DOM macros.
`framework` is not a project option in `stillwind.config.ts`. If an official
integration supplies the wrong constraint, report the error with the component
and the Stillwind package versions.
# SW02002: Unresolved root stylesheet
> The stylesheet that the css setting selects cannot be found.
Source: https://stillwind.dev/docs/errors/SW02002 · Markdown: https://stillwind.dev/docs/errors/SW02002/index.md
This error occurs when the stylesheet that the `css` setting of the project
selects cannot be found. Stillwind reads the theme, utilities, and variants from
that stylesheet, so it cannot compile without it.
## Reported
**stillwind.config.ts**
```ts
import { defineConfig } from "stillwind/config";
export default defineConfig({
projects: [
{
css: "./src/stilwind.css",
files: ["src/**/*.tsx"],
},
],
});
```
> SW02002: the root CSS source cannot be unresolved
## Fixed
```ts title="stillwind.config.ts"
import { defineConfig } from "stillwind/config";
export default defineConfig({
projects: [
{
css: "./src/stillwind.css",
files: ["src/**/*.tsx"],
},
],
});
```
## How to fix
- Check the path in `css`. It is relative to the `root` of the project, or to the
configuration file when `root` is not set.
- If you write your own integration, answer the request for the root stylesheet
with its source text. Only imported stylesheets may be unresolved.
# SW03001: Generated identifier collision
> Two different styles would receive the same generated name.
Source: https://stillwind.dev/docs/errors/SW03001 · Markdown: https://stillwind.dev/docs/errors/SW03001/index.md
This error occurs when two different styles, refs, or animations would receive
the same generated name. The usual cause is a custom `naming` function that
returns the same name for different requests. A very short `hashLength` can also
cause it.
## Reported
**stillwind.config.ts**
```ts
import { defineConfig } from "stillwind/config";
export default defineConfig({
projects: [
{
css: "./src/stillwind.css",
files: ["src/**/*.tsx"],
namingRevision: "1",
naming: {
utilityClass: () => "button",
},
},
],
});
```
```tsx
style("p-4");
style("p-8");
```
> SW03001: generated identifier collision: button
## Fixed
```ts title="stillwind.config.ts"
import { defineConfig } from "stillwind/config";
export default defineConfig({
projects: [
{
css: "./src/stillwind.css",
files: ["src/**/*.tsx"],
namingRevision: "2",
naming: {
utilityClass: (_context, hash) => `button_${hash.toString("hex")}`,
},
},
],
});
```
```tsx
style("p-4");
style("p-8");
```
## How to fix
- Include the hash passed as the callback's second argument in the name, as in
the example. This keeps the `button` prefix while distinguishing requests.
Return `null` to use the default name for a request.
- If you use the default names, raise `hashLength`.
- Change `namingRevision` whenever you change a `naming` function.
# SW03002: Identifier generator failed
> A custom naming function threw an error or returned an invalid name.
Source: https://stillwind.dev/docs/errors/SW03002 · Markdown: https://stillwind.dev/docs/errors/SW03002/index.md
This error occurs when a custom `naming` function fails while it generates a
name. The message shows which kind of name it was generating and the error from
the function. The compiler does not invent a name in its place.
## Reported
**stillwind.config.ts**
```ts
import { defineConfig } from "stillwind/config";
export default defineConfig({
projects: [
{
css: "./src/stillwind.css",
files: ["src/**/*.tsx"],
namingRevision: "1",
naming: {
utilityClass(context, hash) {
if (!context.module.endsWith("Button.tsx")) {
throw new Error("Only Button.tsx is supported");
}
return `button_${hash.toString("hex")}`;
},
},
},
],
});
```
```tsx
style("p-4");
```
> SW03002: identifier generation failed for class: Error: Only Button.tsx is supported
## Fixed
```ts title="stillwind.config.ts"
import { defineConfig } from "stillwind/config";
export default defineConfig({
projects: [
{
css: "./src/stillwind.css",
files: ["src/**/*.tsx"],
namingRevision: "2",
naming: {
utilityClass(context, hash) {
if (!context.module.endsWith("Button.tsx")) {
return null;
}
return `button_${hash.toString("hex")}`;
},
},
},
],
});
```
```tsx
style("p-4");
```
The custom name still applies to `Button.tsx`. Other modules use default names.
## How to fix
- Reproduce the request from the message, and fix the function so that it returns
a name or `null` to keep the default name.
- Keep the function pure: the same request must always produce the same name.
- Change `namingRevision` whenever you change the function.
# SW03003: Theme variable collision
> A theme variable takes the name of a custom property that Stillwind uses internally after themePrefix applies.
Source: https://stillwind.dev/docs/errors/SW03003 · Markdown: https://stillwind.dev/docs/errors/SW03003/index.md
This error occurs when `themePrefix` gives a theme variable the same name as a
custom property that Stillwind registers for its utilities. The two values would
replace each other, so the utilities that use them would break.
## Reported
With `themePrefix: "--tw-"`, the token below becomes `--tw-blur`. The `blur`
utility already uses that property for its own value.
```css
@theme {
--blur: 3px;
}
```
## Fixed
```css
@theme {
--blur-card: 3px;
}
```
## How to fix
- Rename the token so that its output name is free, as in the example.
- Or set `tailwindPrefix` to another value, so that the internal properties
move out of the theme prefix. Plugins that write `--tw-` directly can stop
working when the two prefixes differ, so test them.
# SW10001: JavaScript parse error
> The JavaScript or TypeScript of a file has a syntax error.
Source: https://stillwind.dev/docs/errors/SW10001 · Markdown: https://stillwind.dev/docs/errors/SW10001/index.md
This error occurs when the compiler cannot parse the JavaScript or TypeScript of
a file. The message shows the location and the explanation from the parser.
## Reported
```tsx
export const props = style("p-4";
```
> SW10001: JavaScript parse error
>
> Expected `,` or `)` but found `;`
## Fixed
```tsx
export const props = style("p-4");
```
## How to fix
- Fix the syntax at the location in the message, as in the example.
- If the file parses in your editor, check that the integration treats it as the
right language, such as TypeScript with JSX for a `.tsx` file.
Errors in code that a Vue, Svelte, or Astro converter generated are reported as
[SW31004](/docs/errors/SW31004) instead.
# SW10002: Invalid component syntax
> A Vue, Svelte, or Astro component has a syntax error.
Source: https://stillwind.dev/docs/errors/SW10002 · Markdown: https://stillwind.dev/docs/errors/SW10002/index.md
This error occurs when the parser of the framework cannot read a Vue, Svelte, or
Astro component. The message shows the location and the explanation from that
parser.
## Reported
```html
```
> SW10002: invalid component syntax: SyntaxError: Element is missing end tag.
>
> Source format: Vue
>
> Converter: @vue/language-core@3.3.14
## Fixed
```html
```
## How to fix
Fix the syntax at the location in the message, as in the example, where the
`