PostCSS Plugin

Purpose and Scope

The PostCSS integration is the first-party way to run Tailwind CSS inside a PostCSS pipeline. It is the package users install when a framework, bundler, or application already has PostCSS as the CSS transformation layer. The official setup path tells users to install Tailwind CSS, the PostCSS plugin package, and PostCSS itself, register the plugin in the PostCSS configuration, import Tailwind from a CSS file, and then let their normal build command produce the final stylesheet. In repository terms, the package is named @tailwindcss/postcss, publishes only its built distribution, and exposes a single package root export for both ESM and CommonJS consumers.

Sources: packages/@tailwindcss-postcss/package.json, packages/@tailwindcss-postcss/README.md

This page is a reference for maintainers and integration authors who need to understand what the plugin owns. It covers the package contract, the plugin creator, user-facing options, the way the plugin coordinates with Tailwind’s compiler and scanner, and the small fix-up plugin that protects relative paths when another PostCSS import step has already moved rules around. It does not replace the general installation guide; instead, it explains what happens after a project adds the plugin to its PostCSS configuration and why the available options matter for real build systems.

Sources: packages/@tailwindcss-postcss/src/index.ts, packages/@tailwindcss-postcss/src/postcss-fix-relative-paths/index.ts

Relevant Source Files

  • packages/@tailwindcss-postcss/package.json — Declares the npm package name, version, export map, build scripts, published files, and runtime dependencies on Tailwind core, the Node integration, Oxide, PostCSS, and quick-lru.
  • packages/@tailwindcss-postcss/README.md — Documents the reader-facing plugin API options: base, optimize, and transformAssetUrls, including examples for PostCSS configuration files.
  • packages/@tailwindcss-postcss/src/index.ts — Implements the exported Tailwind PostCSS plugin, its option type, cache entries, compiler and scanner orchestration, early bail-out behavior, optimization choice, and nested helper plugin.
  • packages/@tailwindcss-postcss/src/postcss-fix-relative-paths/index.ts — Implements the companion PostCSS plugin that rewrites relative paths in source, plugin, and config at-rules after import processing.

Public Entry Point and Package Contract

The package manifest makes @tailwindcss/postcss a public package rather than an implementation detail of the core tailwindcss package. Its export map points the package root to generated JavaScript and type declaration files for both import and require consumers, which is important because PostCSS configurations appear in both module systems across the ecosystem. The manifest also shows that the source is built with tsup-node, linted with TypeScript, and published with the dist directory only. That contract keeps application projects depending on the stable package root instead of importing internal TypeScript source files or monorepo paths.

Sources: packages/@tailwindcss-postcss/package.json

The dependency list explains the plugin’s position in the larger Tailwind v4 toolchain. It depends on tailwindcss for the CSS language and AST structures, @tailwindcss/node for compilation, optimization, environment helpers, instrumentation, and Node-specific support, and @tailwindcss/oxide for scanning class candidates. It also depends on PostCSS because it must run as a PostCSS plugin, and quick-lru because compiled state is cached across builds. These dependencies show that this package is not merely a thin wrapper around a string transform; it is the bridge that translates a PostCSS document into Tailwind’s compiler model and then returns a PostCSS-compatible result.

Sources: packages/@tailwindcss-postcss/package.json, packages/@tailwindcss-postcss/src/index.ts

Core Primitives and Options

The exported plugin creator accepts a PluginOptions object. The base option changes the directory used when scanning for class candidates and defaults to the current working directory. This is useful when PostCSS runs from a workspace root, framework cache directory, or package subdirectory but the application source lives somewhere else. The README frames base as the way to change where the plugin searches for source files, while the implementation resolves the effective base before constructing the returned PostCSS plugin object. Treat base as part of the scanning contract, not as a cosmetic path label.

Sources: packages/@tailwindcss-postcss/README.md, packages/@tailwindcss-postcss/src/index.ts

The optimize option controls Lightning CSS optimization and minification behavior through the Node integration. When the option is not supplied, the implementation enables optimization when NODE_ENV is production and disables it otherwise. The README documents three practical modes: leave the default environment-based behavior in place, pass a boolean to force optimization on or off, or pass an object such as minify false to keep optimization enabled while disabling minification. This distinction matters for frameworks that perform their own minification, for debugging production-like builds, and for tests that need stable readable CSS output.

Sources: packages/@tailwindcss-postcss/README.md, packages/@tailwindcss-postcss/src/index.ts

The transformAssetUrls option controls whether the plugin rewrites CSS asset URLs. The README says this rewriting is enabled by default because the plugin also handles imports, so projects do not need a separate postcss-import step for Tailwind’s own import handling. The implementation mirrors that documentation by defaulting shouldRewriteUrls to true. Disabling the option is appropriate when a bundler or framework already owns URL rewriting and double transformation would be confusing or incorrect. In integration code, this option should be decided alongside the surrounding CSS asset pipeline, not independently from it.

Sources: packages/@tailwindcss-postcss/README.md, packages/@tailwindcss-postcss/src/index.ts

Compact option reference

OptionDefaultPurpose
baseCurrent working directoryChanges the directory scanned for class candidates.
optimizeProduction when NODE_ENV is production, otherwise disabledEnables optimization and minification behavior, or accepts an object that can disable minification.
transformAssetUrlstrueEnables or disables rewriting of CSS url values handled by the plugin.

Execution Flow

Calling the plugin creator returns a PostCSS plugin object whose visible postcssPlugin name is @tailwindcss/postcss. That object contains two nested plugins. The first is the relative path fix-up plugin, installed before the main Tailwind plugin so imported CSS can be normalized before compilation. The second is named tailwindcss and implements an asynchronous Once visitor. This shape lets the integration participate naturally in PostCSS’s plugin lifecycle while still composing internal phases that need to run in a specific order.

Sources: packages/@tailwindcss-postcss/src/index.ts, packages/@tailwindcss-postcss/src/postcss-fix-relative-paths/index.ts

The Once visitor begins by creating instrumentation, identifying the input file from the PostCSS result options, and checking whether the file looks like a CSS module by the module stylesheet suffix. It then performs a quick bail check by walking at-rules. If the input does not contain Tailwind-relevant directives or at-rules such as import, reference, theme, variant, config, plugin, apply, or tailwind, the plugin returns early. This is an important performance guard for applications where PostCSS may process many ordinary CSS files that have nothing to do with Tailwind.

Sources: packages/@tailwindcss-postcss/src/index.ts

When the plugin cannot bail out, it retrieves a cache entry keyed by input file, base, and optimization settings. The cache entry stores file modification times, a compiler, a scanner, Tailwind CSS AST data, cached and optimized PostCSS roots, and paths that force a full rebuild. The cache is bounded by QuickLRU with a maximum size of fifty entries. This design supports repeated builds in watch mode without assuming that every CSS file can share one global compiler instance. It also means changes to the base directory or optimization settings intentionally create a different cache context.

Sources: packages/@tailwindcss-postcss/src/index.ts

The source imports conversion helpers that translate between PostCSS ASTs and Tailwind’s CSS AST representation. That mapping is central to the plugin’s role: PostCSS owns the host pipeline and the input root, while Tailwind’s compiler consumes and produces its own AST structures. The plugin also imports toCss and AstNode from Tailwind’s source, compileAst and optimize from the Node package, and Scanner from Oxide. Together, these imports show the execution pipeline: receive a PostCSS root, convert or compile through Tailwind, scan content with Oxide when needed, optimize through Node support when configured, and finally hand a PostCSS root back to the host pipeline.

Sources: packages/@tailwindcss-postcss/src/index.ts

Relative Path Fix-up Plugin

The fix-up plugin solves a specific integration edge case. If postcss-import or another import-capable step has already run before Tailwind, at-rules originating in imported files may now be located under a different root stylesheet. Relative paths inside source, plugin, or config directives would then be interpreted from the wrong directory unless they are rewritten. The helper plugin walks matching at-rules and recalculates relative paths from the imported file’s directory to the root stylesheet’s directory. This preserves the author’s intent while allowing projects that already use PostCSS import processing to continue working.

Sources: packages/@tailwindcss-postcss/src/index.ts, packages/@tailwindcss-postcss/src/postcss-fix-relative-paths/index.ts

The implementation is deliberately conservative. It only operates when both the root file and the at-rule’s input file are known, skips at-rules it has already touched with a WeakSet, and only rewrites quoted parameters. It supports either single or double quotes, preserves one leading negation marker for negative glob-like rules, and ignores paths that do not start with a relative prefix. After computing a normalized POSIX path, it restores a leading dot when the relative calculation would otherwise make a same-directory path appear non-relative. Those checks reduce surprising rewrites and avoid infinite processing loops.

Sources: packages/@tailwindcss-postcss/src/postcss-fix-relative-paths/index.ts

Configuration Examples

A typical PostCSS configuration uses the package root as a plugin entry. Frameworks may express this as an object map or as an imported plugin creator. The official installation flow uses an object-style configuration with @tailwindcss/postcss enabled, then imports Tailwind CSS from an application stylesheet. The README examples use direct imports when passing options, which is often clearer once a project needs to set a custom base, force optimization behavior, or disable asset URL rewriting.

Sources: packages/@tailwindcss-postcss/README.md

import tailwindcss from '@tailwindcss/postcss'
 
export default {
  plugins: [
    tailwindcss({
      base: './app',
      optimize: { minify: false },
      transformAssetUrls: false,
    }),
  ],
}

Use the base option when the scanner should resolve candidates relative to a deliberate application directory. Use optimize false when another stage owns CSS optimization or when readable output is more valuable than compressed output. Use optimize with minify false when you still want optimization features but not minification. Use transformAssetUrls false when the surrounding framework already rewrites URLs from CSS imports. In all cases, keep the application stylesheet simple: import Tailwind CSS, then let the PostCSS build process run as part of the framework or bundler command.

Sources: packages/@tailwindcss-postcss/README.md, packages/@tailwindcss-postcss/src/index.ts

For troubleshooting, first determine whether the file being processed contains a Tailwind-relevant at-rule. The plugin intentionally returns early for files without those signals, so missing output can come from processing the wrong stylesheet or from failing to import Tailwind CSS. Next, verify the base directory when class detection misses templates, because scanning starts from that configured base. Then check optimization and URL rewriting only after compilation is known to run. These options affect the final CSS and asset references, but they do not replace the need for Tailwind directives, imports, and reachable source files.

Sources: packages/@tailwindcss-postcss/src/index.ts, packages/@tailwindcss-postcss/README.md

Read the Using PostCSS installation page first if you are wiring up an application. Read the tailwindcss package API page to understand the compiler that this plugin invokes, the Node API page for compile and optimization behavior shared by integrations, and the Detecting Classes in Source Files page for scanning details. For projects not built around PostCSS, compare the Vite plugin and CLI reference pages before choosing an integration path. Contributors changing this package should keep the public README options, package export map, and implementation defaults aligned so framework guides stay accurate.