stillwind.config.ts describes your projects. The build integration, the CLI,
and the editor all read the same file.
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.
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 |
sort |
Where stillwind fmt sorts utilities, or false to disable them; see 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 |
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 show: themeValues, pixelEquivalents, and colorEquivalents |
The shared configuration API
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 explains
where the rules run.
Presets and severities
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 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.
Rule options
Some rules accept options. Write the rule as an object with severity and the
options:
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. |
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 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.
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
--:
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 <rule> |
The next line |
swlint-disable-line <rule> |
The same line |
swlint-disable <rule> … swlint-enable <rule> |
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 reports a malformed comment, and unused-lint-suppression reports a comment that suppresses nothing.
Sorting
The sort field controls where stillwind fmt, the editor, and the
Prettier plugin 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 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:
- If the integration has a
projectoption, it selects the project with thatname. - Otherwise, it selects the project whose
rootis 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:
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.