React 19 + Tailwind CSS v4: The Complete Setup Guide
Everything you need to set up React 19 with Tailwind CSS v4 — from project creation to theming, dark mode, and your first component. No config files needed.
By Ninna UI Team
React 19 and Tailwind CSS v4 are a powerful combination — React's latest features meet Tailwind's CSS-first rewrite. This guide walks through a complete setup from scratch, including theming, dark mode, and your first accessible component.
1. Create a Vite + React 19 project
npm create vite@latest my-app -- --template react-ts
cd my-app && npm install2. Install Tailwind CSS v4
Tailwind v4 uses a Vite plugin instead of PostCSS. Install the plugin and the CLI:
npm install tailwindcss @tailwindcss/viteAdd the plugin to your Vite config:
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import tailwindcss from "@tailwindcss/vite";
export default defineConfig({
plugins: [react(), tailwindcss()],
});3. Set up CSS (no config file)
Tailwind v4 is CSS-first. There is no tailwind.config.ts. Replace your src/index.css with:
@import "tailwindcss";
/* Dark mode variant */
@variant dark (&:is(.dark *));That's it for Tailwind. No config file, no content paths, no theme object. Everything is CSS.
4. Add a component library (optional)
Install Ninna UI for 69 accessible, themed components:
npm install @ninna-ui/core @ninna-ui/primitives @ninna-ui/forms @ninna-ui/layoutAdd a theme preset to your CSS:
@import "tailwindcss";
@import "@ninna-ui/core/theme/presets/default.css";
@variant dark (&:is(.dark *));5. Dark mode toggle
With CSS-first theming, dark mode is just a class toggle:
document.documentElement.classList.toggle("dark");No provider, no context, no re-render. The browser handles the theme switch through CSS.
6. Your first component
import { Button, Heading, Input } from "@ninna-ui/primitives";
import { Field } from "@ninna-ui/forms";
import { VStack } from "@ninna-ui/layout";
export function NewsletterForm() {
return (
<VStack gap="4" as="form">
<Heading as="h1" size="2xl">Subscribe</Heading>
<Field label="Email">
<Input type="email" placeholder="you@example.com" />
</Field>
<Button type="submit" color="primary">Subscribe</Button>
</VStack>
);
}Wrapping up
You now have a React 19 + Tailwind CSS v4 project with accessible components, oklch theming, and dark mode — all without a single config file. The CSS-first approach means your build is faster, your bundle is smaller, and your theming is more maintainable.