#20426·Tailwind CSS

`@tailwindcss/vite` discards `resolve.conditions` when resolving CSS `@import`, but honours them for JS

Author: jeffberryCreated Aug 20, 2026Updated Aug 22, 2026

What version of Tailwind CSS are you using?

v4.3.3 (@tailwindcss/vite 4.3.3; also reproduces on 4.1.18)

What build tool are you using?

Vite 8 (the relevant code is unchanged across the plugin's ^5.2.0 || ^6 || ^7 || ^8 peer range)

Describe your issue

@tailwindcss/vite builds two resolvers. The JS one inherits the user's resolve config as-is; the CSS one spreads that config and then overwrites conditions with a hardcoded list:

// dist/index.mjs (4.3.3), lightly de-minified
let cssResolver = createIdResolver(config, {
  ...config.resolve,                                  // inherits alias, dedupe, …
  extensions: [".css"],
  mainFields: ["style"],
  conditions: ["style", "development|production"],    // ← replaces user conditions
  tryIndex: false,
  preferRelative: true,
})
let jsResolver = createIdResolver(config, config.resolve)   // ← conditions preserved

Because conditions is assigned after the spread, any custom condition set via resolve.conditions is silently dropped for CSS @import, while continuing to work for JS. The two resolvers therefore disagree about which copy of a package they are looking at.

This is the standard monorepo setup where a library's exports map carries a custom condition so a workbench/dev app consumes source while published consumers get the build output:

// packages/my-lib/package.json
{
  "exports": {
    ".":           { "source": "./src/index.ts",  "default": "./dist/index.js" },
    "./style.css": { "source": "./src/style.css", "default": "./dist/style.css" }
  },
  "files": ["dist", "package.json"]
}
// apps/workbench/vite.config.js
export default {
  resolve: { conditions: ["source", ...] },
  plugins: [tailwindcss()],
}
/* apps/workbench/style.css */
@import "tailwindcss";
@import "my-lib/style.css";
/* packages/my-lib/src/style.css — copied verbatim to dist/ at build time */
@import "tailwindcss";
@source "./**/*.{ts,tsx,js}";   /* relative: src/ in the workspace, dist/ once published */

Expected

my-lib/style.css resolves through the source condition to packages/my-lib/src/style.css, so its relative @source scans src/.

Actual

The source condition is discarded, resolution falls through to default, and packages/my-lib/dist/style.css is loaded — so @source scans dist/.

The app therefore renders components from src/ while scanning dist/ for class candidates. Any utility added since the last build is missing from the generated CSS, and the only symptom is a component that renders unstyled. It looks exactly like a broken component rather than a stale-cache problem, so it is unusually expensive to diagnose — a rebuild makes it disappear, which also makes it hard to reproduce reliably.

Worth noting there is no way to work around this from the exports map. Adding a "style" condition (which the hardcoded list would match) does not help: export conditions cannot distinguish in-repo from published consumption, and src/ is not in files, so every published consumer would resolve to a path that does not exist.

Suggested fix

Append rather than replace, so user conditions survive alongside the CSS-specific ones:

conditions: ["style", "development|production", ...(config.resolve.conditions ?? [])],

If overriding is deliberate, it would help to document it — the asymmetry with the JS resolver two lines away reads as accidental.

Reproduction

Current workaround for anyone hitting this: bypass the export map and import the library's CSS entry by relative path, so no condition resolution is involved.

Source: tailwindlabs/tailwindcss