Skip to content

Configuration

Set up projects in stillwind.config.ts, choose lint rules, and look up every project field.

stillwind.config.ts describes your projects. The build integration, the CLI, and the editor all read the same file.

stillwind.config.tsts
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.

stillwind.config.tsts
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

stillwind.config.tsts
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:

  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:

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.