className, Conditional Classes, Setup
Tailwind with React
Wire Tailwind v4 into a React and Vite app and manage conditional class names cleanly without breaking content detection.
What you'll learn
- Add the @tailwindcss/vite plugin to a React app
- Compose classes with template literals or clsx
- Avoid dynamic class string pitfalls
React uses className instead of class, but Tailwind v4 setup is otherwise the same lightweight story: one Vite plugin and one CSS import.
Setup in a Vite React App
Add the first-party Vite plugin and import Tailwind from your CSS entry. No tailwind.config.js is required in v4.
npm install tailwindcss @tailwindcss/vite // vite.config.js
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import tailwindcss from '@tailwindcss/vite';
export default defineConfig({
plugins: [react(), tailwindcss()],
}); /* src/index.css */
@import "tailwindcss"; Conditional Classes
Build conditional class names with a template literal or, for anything non-trivial, the clsx helper:
function Tab({ active }) {
return (
<button className={`px-4 py-2 ${active ? 'bg-blue-600 text-white' : 'bg-gray-200 text-gray-700'}`}>
Tab
</button>
);
} The Dynamic Class Trap
Tailwind detects classes by scanning source text for complete class names. A string assembled from fragments is never found, so the CSS is never generated:
// BROKEN: `bg-${color}-500` is never seen by the scanner
<div className={`bg-${color}-500`} />
// GOOD: full class names in a lookup map
const bg = { red: 'bg-red-500', blue: 'bg-blue-500' };
<div className={bg[color]} /> Always write complete class strings or map known keys to complete strings.
Tailwind with Vue & Svelte →