tailwind v4 + chakra ui: five bugs and how to fix them
I just wanted to use bg-blue-500 on one button. Four hours later, I was deep in CSS specificity rabbit holes wondering why my styles kept disappearing.
If you're trying to use Tailwind CSS v4 alongside Chakra UI in a Next.js project, you've probably hit the same problems. Here's what broke and how I fixed it.
why use both
Sounds insane. Two CSS frameworks in one project?
But I had a big Chakra UI app. I wanted Tailwind's utility classes for new pages. A full rewrite wasn't an option.
Real reasons to do this:
- Slow migration from Chakra to Tailwind
- Team knows different tools
- Chakra components + Tailwind quick styling
- Fast prototyping for new features
bug 1: the config file lie
I had a tailwind.config.js file. Nothing worked.
Spent 30 minutes tweaking the config. Then I checked package.json. The packages weren't installed. The config was completely unused.
npm install -D tailwindcss @tailwindcss/postcss postcss autoprefixerA config file means nothing without the packages.
bug 2: the postcss plugin switcheroo
Tailwind v4 changed how it integrates with PostCSS. The old way throws this error:
It looks like you're trying to use `tailwindcss` directly as a PostCSS pluginv4 moved its PostCSS plugin to @tailwindcss/postcss:
// postcss.config.js - v4 way
module.exports = {
plugins: {
"@tailwindcss/postcss": {},
autoprefixer: {},
},
};Not this:
// DON'T DO THIS - v3 way
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};bug 3: the invisible padding
Added p-4 to a div. Nothing happened.
DevTools showed the class was there. But a global reset was winning:
* {
padding: 0;
margin: 0;
}CSS without a layer beats CSS with a layer. Tailwind uses layers. My reset didn't.
Fix: wrap base CSS in @layer base:
@layer base {
* {
box-sizing: border-box;
padding: 0;
margin: 0;
}
}bug 4: the vanishing background
Added bg-primary-500 to a div. Class was there. DevTools showed backgroundColor: transparent.
Chakra UI uses Emotion (CSS-in-JS). Emotion injects styles after page load. Late styles beat early styles.
Fix: add important to your Tailwind import:
@import "tailwindcss" important;
@source "../**/*.{js,jsx,ts,tsx}";That one word adds !important to all Tailwind styles. Now they win against Emotion's late arrivals.
This is the most important fix. Without it, half your Tailwind classes randomly fail near Chakra components.
bug 5: the color palette mystery
Built a color grid to test my theme. Some boxes showed colors. Others were blank.
Pattern: only colors written directly worked. Colors from variables didn't.
Tailwind's JIT compiler scans your code for class names. It can't see names built from variables:
// BROKEN - JIT can't find this
const bgClass = `bg-${color}-${shade}`;
// WORKS - JIT can find this
const bgClass = "bg-primary-500";Fix: use a lookup object with all class names spelled out:
const colorClasses = {
primary: {
50: "bg-primary-50",
100: "bg-primary-100",
500: "bg-primary-500",
// ...
},
} as const;
<div className={colorClasses[color][shade]} />Verbose, but works every time.
debugging checklist
| Problem | Check |
|---|---|
| Nothing works | Are packages in package.json? |
| PostCSS error | Using @tailwindcss/postcss for v4? |
| Styles disappear near Chakra | Added important to import? |
| Resets override Tailwind | Base styles in @layer base? |
| Dynamic classes missing | Using lookup object instead of template literals? |
Two CSS frameworks can coexist. You just need to know where the conflicts are.
That said, this is probably not a good idea.