Using Vite

Purpose and Scope

This page explains the Vite-first installation path for Tailwind CSS and how it maps to the first-party @tailwindcss/vite package in the monorepo. Use it when you are starting a Vite application, integrating Tailwind into a Vite-powered framework, or deciding whether to use the Vite plugin instead of the PostCSS plugin or CLI. In Tailwind CSS v4, the Vite path is the most direct option for Vite-native stacks because Tailwind participates in Vite’s plugin pipeline rather than being wired as a separate PostCSS-only step.

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

The official setup flow is intentionally small: create or open a Vite project, install tailwindcss and @tailwindcss/vite, add the plugin to vite.config.ts, import Tailwind from your CSS, and run the development server. Tailwind still works by scanning templates and components for class names, generating the corresponding CSS, and writing that CSS into the build output; the Vite plugin is the integration point that lets this happen inside the Vite build and dev-server lifecycle with zero runtime styling code shipped to the browser.

Relevant Source Files

  • packages/@tailwindcss-vite/src/index.ts — implements the default tailwindcss() Vite plugin factory, its PluginOptions, Vite resolver integration, and connections to the Node compiler and Oxide scanner.
  • packages/@tailwindcss-vite/package.json — defines the published package name, public export, dependencies on @tailwindcss/node, @tailwindcss/oxide, and tailwindcss, and the supported Vite peer dependency range.
  • packages/@tailwindcss-vite/README.md — documents the public plugin API for controlling Lightning CSS optimization with the optimize option.
  • playgrounds/vite/package.json — shows the repository’s Vite playground dependencies and scripts for development, production build, preview, and type-checking.
  • playgrounds/vite/src/main.tsx — demonstrates the application entry point importing CSS so Vite includes Tailwind-generated styles in the app graph.
  • packages/@tailwindcss-vite/tsconfig.json — shows that the package builds with the shared monorepo TypeScript configuration.

Core Primitives

The Vite integration has three important primitives. The first is the published package, @tailwindcss/vite, which exposes a default module entry from dist/index.mjs with TypeScript declarations from dist/index.d.mts. The package is versioned with Tailwind, is public, and declares vite as a peer dependency for Vite ^5.2.0 || ^6 || ^7 || ^8. That peer range matters because the plugin source supports both older Vite behavior and newer environment-aware APIs.

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

The second primitive is the plugin factory itself: tailwindcss(opts: PluginOptions = {}): Plugin[]. Its public option surface is deliberately narrow. PluginOptions currently exposes optimize?: boolean | { minify?: boolean }, which controls whether output CSS is optimized and whether optimized CSS is minified. The package README frames this in terms of Lightning CSS: production builds enable optimization by default, development builds disable it by default, and callers can override that behavior when their project needs predictable optimization settings across environments.

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

The third primitive is the project CSS import. Tailwind is brought into the app through a CSS file with @import 'tailwindcss', and that CSS file must be imported by the Vite application or otherwise included by the framework. The repository’s Vite playground follows the common React pattern: main.tsx imports ./index.css before rendering the application. That import is what gives Vite a CSS module to process through its plugin graph, which is where the Tailwind plugin can compile the framework styles.

Sources: playgrounds/vite/src/main.tsx, playgrounds/vite/package.json

Installation Flow

Start with a Vite project. In a new project, the official path uses npm create vite@latest my-project and then changes into the project directory. In an existing Vite app, begin from the app root instead. Install both packages together so the integration package and the core framework resolve from the same dependency graph. The repository playground uses workspace versions of @tailwindcss/vite and tailwindcss, plus Vite, React, and the React plugin, which mirrors the shape of a normal application even though it links local workspace packages for development.

npm install tailwindcss @tailwindcss/vite

Next, add the plugin to your Vite configuration. The default export from @tailwindcss/vite is a function, so the Vite config calls tailwindcss() inside the plugins array. In a React app, this usually sits alongside @vitejs/plugin-react; in framework adapters, the framework may own the surrounding Vite config but still exposes a place for Vite plugins. The important detail is that Tailwind should be registered as a Vite plugin, not as the PostCSS package, when following this page’s setup path.

import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite'
 
export default defineConfig({
  plugins: [tailwindcss()],
})

Finally, import Tailwind from CSS and make sure that CSS participates in the Vite module graph. In the official quick start, that means adding @import 'tailwindcss' to a stylesheet and linking or importing it from the app. In the repository playground, the React entry point imports ./index.css, then renders the App component through ReactDOM.createRoot. This is the practical handoff between application code and the Tailwind compiler: templates and components provide class candidates, while the CSS entry asks Tailwind to generate the style output.

@import 'tailwindcss';

System-to-Code Mapping

The Vite package is a thin integration layer over shared Tailwind internals rather than a separate compiler. Its source imports compile, optimize, toSourceMap, normalizePath, Instrumentation, and Features from @tailwindcss/node, and imports Scanner from @tailwindcss/oxide. That tells you where responsibilities are split: the Vite package adapts Vite’s lifecycle, the Node package provides the JavaScript-facing compilation and optimization APIs, and Oxide provides the fast scanner used to detect class names in source files.

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

Vite resolution is also part of the integration. The source defines createCustomResolver, which receives resolver functions and returns an async resolver that resolves an id relative to a base directory using a placeholder importer. It filters resolved paths, normalizes relative resolutions into absolute paths, rejects unresolved or non-absolute results, and supports separate CSS and JavaScript resolution behavior. This is important for real projects because Tailwind CSS files can import other CSS, reference JavaScript configuration or plugin code, and run under different Vite resolver conditions.

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

The plugin source tracks Vite servers, resolved config, environment roots, SSR state, optimization state, and minification state. It also contains compatibility handling for older pre-environment Vite APIs and newer environment-aware APIs. That compatibility is reflected in the package peer dependency range, which spans several major Vite versions. For application developers, this means the public setup remains stable, while the plugin absorbs differences in Vite’s internal resolver and environment model.

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

Plugin Options Reference

Entry pointSignature or fieldMeaning
Default exporttailwindcss(opts?: PluginOptions): Plugin[]Registers Tailwind CSS with Vite.
PluginOptions.optimize`boolean{ minify?: boolean }`
Package export.Resolves to ./dist/index.mjs with ./dist/index.d.mts types.
Peer dependencyviteSupports `^5.2.0

Use optimize: false when you want to disable Lightning CSS optimization even in a production-like environment. Use optimize: { minify: false } when you still want Lightning CSS processing but need readable, non-minified output, for example when debugging generated CSS or inspecting a build artifact. If you do not pass the option, the README describes environment-based behavior: production enables optimization and development disables it, matching the usual tradeoff between fast iteration and compact production output.

import tailwindcss from '@tailwindcss/vite'
import { defineConfig } from 'vite'
 
export default defineConfig({
  plugins: [
    tailwindcss({
      optimize: { minify: false },
    }),
  ],
})

Playground and Verification Signals

The repository’s Vite playground is the best source-backed example for verifying the integration shape. Its package scripts run Vite against ./src with an explicit vite.config.ts, provide separate dev, build, and preview commands, and include a lint script that runs TypeScript without emitting output. Its dependencies include the workspace @tailwindcss/vite package and workspace tailwindcss, which makes the playground useful for exercising local changes to the plugin against an actual Vite application.

Sources: playgrounds/vite/package.json, playgrounds/vite/src/main.tsx

When debugging a Vite setup, first check that @tailwindcss/vite is installed next to tailwindcss, then confirm that tailwindcss() appears in the Vite plugins array, and finally verify that a stylesheet importing Tailwind is included by the app. If those pieces are present, move to framework-specific concerns such as where the framework expects global CSS imports or how it customizes Vite config. For non-Vite build chains, continue to the PostCSS, CLI, or framework guide pages instead of forcing the Vite package into a pipeline it does not own.