Tailwind CSS

esdev compiles Tailwind CSS v4 itself. There is no plugin to add and no configuration file: install tailwindcss and import it.

Shell
npm install -D tailwindcss
CSS
/* src/styles.css */
@import "tailwindcss";
HTML
<link rel="stylesheet" href="./src/styles.css" />

esdev build and esdev start now generate the utilities your project uses. The compiler is your project's own tailwindcss, so the Tailwind version is the one in your package.json.

A new project can start this way:

Shell
esdev create my-app --template=react --styling=tailwind

Where it applies

Any stylesheet that imports tailwindcss or uses a Tailwind directive — @theme, @apply, @utility, @variant, @custom-variant, @plugin, @config, @reference, @source — is compiled, however it reaches the build:

Linked from an HTML entry<link rel="stylesheet" href="./styles.css">
Imported from a moduleimport "./styles.css";
A CSS Moduleimport styles from "./Button.module.css";
A stylesheet entryesdev build src/styles.css --out=dist/app.css

Every other stylesheet is left as it was. The output goes through the same pipeline as any stylesheet: local @imports are inlined, url() references are copied and rewritten, and --minify minifies.

Where class names are found

esdev scans your project for class names the way Tailwind does:

  • Every file under the project directory — the nearest directory above the stylesheet with an esdev.json or package.json — is read.

  • Files your .gitignore ignores are skipped, as are node_modules, stylesheets, lock files and binary files.

Name other paths with @source, including ones .gitignore would skip:

CSS
@import "tailwindcss";
@source "../node_modules/@acme/ui";
@source not "./src/legacy";

A path is relative to the stylesheet that wrote it, including in a stylesheet another one @imports. To scan one directory instead of the project, or to turn automatic detection off:

CSS
@import "tailwindcss" source("../src");
CSS
@import "tailwindcss" source(none);
@source "./components";

A class name must appear in full in the source. text-{color}-500 built from a variable is never found; write the full names, or list them with @source inline("text-red-500 text-green-500").

Plugins and CSS Modules

@plugin loads a plugin from a package or from a path beside the stylesheet:

CSS
@import "tailwindcss";
@plugin "@tailwindcss/typography";
@plugin "./tailwind/tab-size.js";

A CSS Module uses @apply against your theme with @reference, which makes the theme available without emitting it again:

CSS
/* Button.module.css */
@reference "../styles.css";

.button {
  @apply rounded px-3 py-1 text-white bg-brand;
}

Errors

A build that cannot compile a stylesheet fails with Tailwind's own message, and writes nothing:

TEXT
error: cannot compile src/styles.css with Tailwind: Cannot apply unknown utility class `bg-brnd`

A stylesheet that uses Tailwind in a project that has not installed it fails with the command to run, rather than shipping @import "tailwindcss" to the browser.

Tailwind v4 only

Tailwind v3 is configured by a JavaScript file run through PostCSS, which esdev does not run. A project with tailwindcss 3 installed is told to upgrade: npm install -D tailwindcss@4.

The dev loop keeps classes until the stylesheet changes

Under esdev start, a class you remove from a component stays in the served CSS until the stylesheet itself is edited or the loop restarts. A release build always starts clean.

How the compiler and the scanner fit into esdev is described in Internals: Tailwind CSS.

Last updated on
Edit this page