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.

BySourav Mishra2 min read

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-merge fixes 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:

  1. stop the dev server.
  2. run the build.
  3. restart the dev server.

my debugging checklist

  1. delete .next folder: run rm -rf .next and build locally to reproduce the error.
  2. check third-party css: move third-party css to layout.tsx.
  3. 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.

Share this post

Cover image for why your next.js styles break in production (and how to fix them)

You might also like

See all