
How to Use Ant Design (AntD) and Tailwind CSS Together
Are you tired of Ant Design and Tailwind CSS fighting over styles? 😤 You’re not alone. Combining two powerful styling systems sounds risky — but with the right setup, they work side by side beautifully. This guide shows you exactly how to do it, the same approach developers have been using. Why Use Ant Design […]
Are you tired of Ant Design and Tailwind CSS fighting over styles? 😤 You’re not alone.
Combining two powerful styling systems sounds risky — but with the right setup, they work side by side beautifully. This guide shows you exactly how to do it, the same approach developers have been using.
Why Use Ant Design and Tailwind CSS Together?
Ant Design (AntD) gives you a rich, production-ready component library. Tailwind CSS gives you utility-first flexibility for custom layouts and spacing. Together, they cover everything. 🚀
The challenge? Both systems inject CSS globally, and they can conflict — especially around base/reset styles and specificity.
The good news: there’s a clean, official solution.
The Root Problem: CSS Specificity Conflicts
When you import both Tailwind and AntD in the same project, Tailwind’s preflight.css (a CSS reset) can override AntD component styles.
This causes buttons to lose padding, typography to break, and popups to render incorrectly. 😬
The fix involves two steps:
- Use AntD’s
StyleProviderwith CSS-in-JS - Order your CSS layers correctly in Tailwind
Step 1: Wrap Your App with StyleProvider 🛠️
AntD’s team officially recommends using StyleProvider from @ant-design/cssinjs. This moves AntD’s styles into a CSS layer with higher priority, preventing Tailwind from overriding them.
Here’s the ThemeProvider component you need:
import React, { useState } from "react";
import { StyleProvider } from "@ant-design/cssinjs";
import { theme as AntdTheme, ConfigProvider } from "antd";
export default function ThemeProvider({ children, popupContainer }) {
const [theme, setTheme] = useState("light");
const { token } = AntdTheme.useToken();
const currentAlgorithm =
theme === "dark"
? AntdTheme.darkAlgorithm
: AntdTheme.defaultAlgorithm;
return (
popupContainer || document.body}
theme={{
algorithm: currentAlgorithm,
}}
>
{children}
);
}
Let’s break down the key props:
container={document.body}— Injects AntD styles directly into , keeping them scoped and predictable.hashPriority="high"— Gives AntD’s generated class names higher specificity.layer— Wraps AntD styles in a named CSS@layer, which is the key to avoiding conflicts. ✅
The ConfigProvider handles dark/light mode switching via AntD’s built-in algorithms — no extra theming libraries needed.
Step 2: Configure Tailwind CSS Layer Order 🎨
This is where most developers get stuck. In Tailwind CSS v4, you control the CSS layer order explicitly in your main CSS file.
Here’s the correct configuration:
@layer theme, base, antd, components, utilities;
@import "tailwindcss/theme.css" layer(theme);
@import "tailwindcss/preflight.css" layer(base);
@import "tailwindcss/utilities.css" layer(utilities);
@custom-variant dark (&:where(.dark, .dark *));
@layer base {}
Here’s what’s happening line by line:
@layer theme, base, antd, components, utilities; This declares the layer order explicitly. antd is placed after base (where Tailwind’s reset lives) but before utilities. This means AntD styles override the reset, and Tailwind utilities override AntD when needed. 🎯
@import "tailwindcss/preflight.css" layer(base); Tailwind’s CSS reset is now locked inside the base layer, so it can’t bleed into AntD components.
@custom-variant dark (&:where(.dark, .dark *)) This sets up Tailwind’s dark mode to work with a .dark class on the or element — compatible with AntD’s dark algorithm.
@plugin lines Custom Tailwind plugins (like color palettes or scrollbar utilities) load after the core framework — keeping your project-specific styles organized.
Why This Approach Works 💡
CSS @layer is a native browser feature that lets you define cascade order explicitly. Without it, specificity is determined by source order and unpredictable selector weight.
By placing antd between base and utilities:
- AntD components always override Tailwind’s CSS reset ✅
- Tailwind utility classes (
mt-4,text-sm, etc.) always override AntD defaults ✅ - No
!importanthacks needed ✅
Dark Mode Support Out of the Box 🌙
The setup above supports both Tailwind dark mode and AntD dark mode simultaneously.
AntD handles component-level dark theming via AntdTheme.darkAlgorithm. Tailwind handles utility-level dark theming via the .dark class variant.
To toggle dark mode in your app, simply:
- Add/remove the
.darkclass on or - Update the
themestate in yourThemeProviderto"dark"
Both systems update automatically. No duplication, no conflict. 🎉
Compatible With Next.js and Vite ⚡
This setup works with both major React frameworks:
- Next.js (App Router): Add
ThemeProviderto your rootlayout.tsx. Use"use client"since it relies onuseState. - Vite + React: Import
ThemeProviderinmain.tsxand wrap your component.
The CSS layer configuration goes in your global stylesheet (globals.css for Next.js, index.css for Vite).
Common Mistakes to Avoid ⚠️
Not declaring the layer order at the top. The @layer theme, base, antd, components, utilities; declaration must come before your imports. Order matters.
Forgetting the layer prop on StyleProvider. Without it, AntD styles won’t be placed inside a named CSS layer, and conflicts will return.
Using Tailwind v3 syntax with v4 config. The @import with layer() syntax is Tailwind v4 specific. Check your Tailwind version before copying this config.
Wrapping ThemeProvider in a Server Component. Since it uses useState, it must be a Client Component in Next.js App Router.
Frequently Asked Questions ❓
Does this work with Tailwind CSS v3?
The CSS layer ordering syntax (@import ... layer(...)) is a Tailwind CSS v4 feature. For v3, you’ll need a different approach using important strategy or manual layer declarations in a PostCSS config.
Can I still use AntD’s built-in theming tokens?
Yes. The ConfigProvider setup preserves AntD’s full design token system. You can pass custom token values (colors, font sizes, border radius) alongside Tailwind utilities without any conflicts.
Will this affect performance?
No measurable impact. CSS-in-JS with StyleProvider generates styles at build time in production. The layer approach is handled natively by the browser with no JavaScript overhead.
What version of AntD supports StyleProvider?
StyleProvider is available from AntD v5 onwards. If you’re on AntD v4, the CSS-in-JS approach isn’t available, and you’ll need to handle conflicts with postcss or manual specificity overrides.
Can I use this with shadcn/ui too?
Yes. shadcn/ui is Tailwind-native and doesn’t inject global styles aggressively. As long as your layer order is correct, all three can coexist.
Final Thoughts
Using AntD and Tailwind CSS together isn’t just possible — it’s a great combination for production apps. 💪
AntD handles complex UI components (tables, date pickers, modals). Tailwind handles layout, spacing, and custom design. With StyleProvider and proper CSS layer ordering, they stay out of each other’s way.
The setup takes about 10 minutes, and once it’s in place, you won’t think about styling conflicts again.