# Configuring Tailwind CSS 4 with @tailwindcss/vite Plugin in OpenCut: Complete Setup Guide

> Learn to configure Tailwind CSS 4 with the @tailwindcss/vite plugin in OpenCut. Follow our setup guide for efficient styling and class composition in your project.

- Repository: [OpenCut.app/OpenCut](https://github.com/OpenCut-app/OpenCut)
- Tags: how-to-guide
- Published: 2026-06-23

---

**OpenCut configures Tailwind CSS 4 by registering the `@tailwindcss/vite` plugin in [`apps/web/vite.config.ts`](https://github.com/OpenCut-app/OpenCut/blob/main/apps/web/vite.config.ts), importing Tailwind directives via `@import` syntax in [`apps/web/src/styles.css`](https://github.com/OpenCut-app/OpenCut/blob/main/apps/web/src/styles.css), and using a `cn` utility combining `clsx` and `tailwind-merge` for safe class composition.**

OpenCut is an open-source video editing application built with React and Vite. Configuring Tailwind CSS 4 with the `@tailwindcss/vite` plugin in OpenCut requires coordinated setup across the Vite configuration, package dependencies, and global stylesheet to leverage the new JIT compiler architecture and zero-configuration approach.

## How Tailwind CSS 4 Integrates with Vite in OpenCut

Tailwind CSS 4 moves from a PostCSS plugin model to a standalone toolchain. In OpenCut, this integration is orchestrated through three core configuration layers that enable automatic utility generation and native Vite optimization.

### Vite Configuration File

The primary integration point is [`apps/web/vite.config.ts`](https://github.com/OpenCut-app/OpenCut/blob/main/apps/web/vite.config.ts), where the `@tailwindcss/vite` plugin is imported and added to the plugins array. Unlike Tailwind CSS 3, which required a [`postcss.config.js`](https://github.com/OpenCut-app/OpenCut/blob/main/postcss.config.js) file, version 4 operates as a first-class Vite plugin.

```ts
// apps/web/vite.config.ts
import { defineConfig } from 'vite';
import tailwindcss from '@tailwindcss/vite';
// ... other imports

export default defineConfig({
  plugins: [
    tailwindcss(),  // Activates Tailwind CSS 4 JIT compiler
    // ... other plugins
  ],
});

```

By calling `tailwindcss()` within the configuration, the plugin automatically watches source files and generates only the CSS utilities actually used in the application bundle. This eliminates the need for separate PostCSS configuration while providing faster incremental builds.

### Package Dependencies

The required packages are declared in [`apps/web/package.json`](https://github.com/OpenCut-app/OpenCut/blob/main/apps/web/package.json), specifying Tailwind CSS 4 and its Vite integration alongside utility libraries for class name management.

- `tailwindcss@^4.1.18` – The core Tailwind CSS engine.
- `@tailwindcss/vite@^4.1.18` – The official Vite plugin for Tailwind 4.
- `tailwind-merge@^3.5.0` – For resolving conflicting Tailwind classes.
- `clsx` – For conditional class name construction.

### Global Stylesheet Configuration

The entry CSS file at [`apps/web/src/styles.css`](https://github.com/OpenCut-app/OpenCut/blob/main/apps/web/src/styles.css) imports Tailwind CSS 4 using the new module-based `@import` syntax rather than traditional `@tailwind` directives. This file also defines custom variants and imports optional animation libraries.

```css
/* apps/web/src/styles.css */
@import 'tailwindcss';
@import "tw-animate-css";
@import "shadcn/tailwind.css";
@import "@fontsource-variable/inter";

@custom-variant dark (&:is(.dark *));

```

The `@custom-variant dark` declaration creates a dark mode variant that automatically scopes utilities to descendants of any element with the `.dark` class. This enables straightforward theme toggling without manually prefixing every utility with `dark:`.

## Class Name Composition Utilities

OpenCut implements a standardized approach to combining Tailwind classes safely. The `cn` utility function in [`apps/web/src/lib/utils.ts`](https://github.com/OpenCut-app/OpenCut/blob/main/apps/web/src/lib/utils.ts) wraps `clsx` for conditional logic and `tailwind-merge` for conflict resolution.

```ts
// apps/web/src/lib/utils.ts
import { clsx, type ClassValue } from "clsx";
import { twMerge } from "tailwind-merge";

export function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs));
}

```

Components use this helper to merge base styles with conditional overrides. This ensures that later classes take precedence when conflicts occur, such as when overriding `bg-muted` with `bg-primary`, preventing invalid CSS from duplicate property declarations.

## Practical Implementation Examples

### Complete Vite Configuration

The full Vite setup includes additional plugins for React and cloud deployment, with Tailwind CSS 4 integrated seamlessly into the pipeline:

```ts
// apps/web/vite.config.ts
import { defineConfig } from 'vite';
import viteReact from '@vitejs/plugin-react';
import tailwindcss from '@tailwindcss/vite';
import { cloudflare } from '@cloudflare/vite-plugin';
import { devtools } from '@tanstack/devtools-vite';
import { tanstackStart } from '@tanstack/react-start/plugin/vite';

export default defineConfig({
  resolve: { tsconfigPaths: true },
  plugins: [
    devtools(),
    cloudflare({ viteEnvironment: { name: 'ssr' } }),
    tailwindcss(),          // Tailwind CSS 4 integration
    tanstackStart(),
    viteReact(),
  ],
});

```

### Using the cn Helper in Components

React components leverage the `cn` utility imported from `#/lib/utils` (aliased to [`apps/web/src/lib/utils.ts`](https://github.com/OpenCut-app/OpenCut/blob/main/apps/web/src/lib/utils.ts)) to handle dynamic styling:

```tsx
// Example usage in a component
import { cn } from '#/lib/utils';

export function Button({ active }: { active: boolean }) {
  return (
    <button
      className={cn(
        "p-2 rounded-md transition-colors",
        active ? "bg-primary text-primary-foreground" : "bg-muted"
      )}
    >
      Click me
    </button>
  );
}

```

## Summary

- **Zero-configuration setup**: Tailwind CSS 4 integrates directly into Vite via the `@tailwindcss/vite` plugin in [`apps/web/vite.config.ts`](https://github.com/OpenCut-app/OpenCut/blob/main/apps/web/vite.config.ts), removing the need for PostCSS configuration files.
- **Modern import syntax**: The global stylesheet at [`apps/web/src/styles.css`](https://github.com/OpenCut-app/OpenCut/blob/main/apps/web/src/styles.css) uses `@import 'tailwindcss'` to load utilities and defines custom dark mode variants via `@custom-variant`.
- **Dependency management**: Core packages including `tailwindcss@^4.1.18`, `@tailwindcss/vite@^4.1.18`, `tailwind-merge`, and `clsx` are declared in [`apps/web/package.json`](https://github.com/OpenCut-app/OpenCut/blob/main/apps/web/package.json).
- **Safe class merging**: The `cn` utility function in [`apps/web/src/lib/utils.ts`](https://github.com/OpenCut-app/OpenCut/blob/main/apps/web/src/lib/utils.ts) combines `clsx` and `tailwind-merge` to prevent conflicting utility classes in components while supporting conditional logic.

## Frequently Asked Questions

### How does the @tailwindcss/vite plugin differ from PostCSS-based Tailwind setups?

The `@tailwindcss/vite` plugin operates as a standalone Vite plugin rather than a PostCSS plugin, enabling Tailwind CSS 4 to run its own JIT compiler directly within Vite's build pipeline. This eliminates the need for a [`postcss.config.js`](https://github.com/OpenCut-app/OpenCut/blob/main/postcss.config.js) file and provides faster incremental builds by watching source files directly through Vite's module graph rather than the file system.

### What is the cn utility function used for in OpenCut?

The `cn` function in [`apps/web/src/lib/utils.ts`](https://github.com/OpenCut-app/OpenCut/blob/main/apps/web/src/lib/utils.ts) is a composition helper that combines `clsx` for conditional class name logic with `tailwind-merge` for resolving conflicting Tailwind utilities. It ensures that when multiple classes target the same CSS property, the last specified class takes precedence without manual string manipulation, preventing invalid CSS output.

### How is dark mode implemented in OpenCut's Tailwind configuration?

Dark mode is implemented using a custom variant defined in [`apps/web/src/styles.css`](https://github.com/OpenCut-app/OpenCut/blob/main/apps/web/src/styles.css) via the `@custom-variant dark (&:is(.dark *));` directive. This creates a `.dark` class selector that automatically scopes dark mode utilities to descendant elements, allowing developers to toggle themes by adding or removing the `.dark` class on a parent container.

### Where are Tailwind CSS 4 dependencies declared in the project?

All Tailwind CSS 4 related dependencies are declared in [`apps/web/package.json`](https://github.com/OpenCut-app/OpenCut/blob/main/apps/web/package.json), including the core `tailwindcss` package at version `^4.1.18`, the Vite integration plugin `@tailwindcss/vite` at `^4.1.18`, and helper libraries `tailwind-merge` and `clsx` for class name management and conflict resolution.