why your next.js styles break in production (and how to fix them) - By Sourav Mishra (@souravvmishra)
ever had css working perfectly locally but broken in prod? here is why it happens in next.js and how i fix it.
it’s the classic "works on my machine" nightmare. you build a nice ui on localhost:3000. you deploy to vercel, and boom. buttons are the wrong color, layouts shift, fonts flicker.
let's see why next.js styles often break in production and the exact debugging steps i use at codestam.
the real issue: order matters
in development, next.js injects styles on demand. in production, css is bundled into chunks. if your import order is messy, the "winning" style might change.
the global css trap
importing globals.css in a random component is a huge mistake.
❌ bad:
// app/dashboard/page.tsx
import '../globals.css'; // don't do this!
✅ good: import it once in the root layout, at the very top.
// app/layout.tsx
import './globals.css'; // top of the file
import { Inter } from 'next/font/google';
tailwind vs. shadcn
if you use shadcn ui, you might face specificity wars. bg-red-500 might get overwritten by a default bg-blue-500.
solution: tailwind-merge
always use a utility like cn() to merge classes safely.
import { clsx, type ClassValue } from "clsx"
import { twMerge } from "tailwind-merge"
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}
we once spent 3 days debugging a broken button just to realize the classes were conflicting.
tailwind-mergefixes this completely.
hydration mismatches
if your dark mode toggles flash on load, it's a hydration mismatch. the server renders "light" but the client has "dark".
fix: use next-themes with the suppressHydrationWarning prop.
<html lang="en" suppressHydrationWarning>
<body>
<ThemeProvider attribute="class">
{children}
</ThemeProvider>
</body>
</html>
the build-while-dev conflict
running next build while next dev is active breaks styles locally. both fight over the .next folder.
the fix:
- stop the dev server.
- run the build.
- restart the dev server.
my debugging checklist
- delete
.nextfolder: runrm -rf .nextand build locally to reproduce the error. - check third-party css: move third-party css to
layout.tsx. - inspect the build: look for "conflicting order" warnings.
production css issues are almost always due to import order. keep it clean and you'll be fine.
want more next.js tips? check out my guide on mastering cache components.