Tailwind CSS Not Working? The Complete Fix Guide for 2026
If you’re reading this, chances are you’ve just set up Tailwind CSS (or updated an existing project), and your styles look like they’ve completely vanished. You refresh the page, check your class names, and everything looks correct — but the utility classes just refuse to apply. It’s frustrating, but the good news is that the problem almost always boils down to one of a handful of root causes.
This guide walks you through every common — and several uncommon — reason Tailwind CSS might not be working, with step-by-step diagnostics and copy-paste-ready fixes. I’ve been through every one of these scenarios myself, so I’ll share the shortcuts that actually save time.
Understanding Why Tailwind CSS Breaks
Before diving into fixes, it helps to understand how Tailwind works under the hood. Unlike traditional CSS frameworks (Bootstrap, Bulma), Tailwind doesn’t ship a pre-built stylesheet. Instead, it scans your files for class names and generates a CSS file containing only the utilities you actually use. This is called the “content detection” or “purge” step.
That architecture is what makes Tailwind fast and lightweight — but it also means there are more moving parts that can fail:
- The build process needs to run
- The configuration file needs to know where to look
- The generated CSS needs to actually reach the browser
- The right version needs to be installed and compatible
When any link in that chain breaks, your styles disappear. Let’s go through each one.
Step 1: Verify Tailwind Is Actually Installed
It sounds obvious, but the number one cause of “Tailwind not working” is that it isn’t installed — or only installed in the wrong place. If you have a monorepo or multiple package.json files, you might have installed it in the root instead of the app directory.
Check your package.json:
cat package.json | grep tailwind
If you’re using Tailwind v4 (the current major release as of 2026), you should see something like:
{
"devDependencies": {
"tailwindcss": "^4.0.0",
"@tailwindcss/postcss": "^4.0.0"
}
}
For v3 projects still on the legacy stack:
{
"devDependencies": {
"tailwindcss": "^3.4.0",
"postcss": "^8.4.0",
"autoprefixer": "^10.4.0"
}
}
If the package is missing, install it:
npm install tailwindcss @tailwindcss/postcss
Step 2: Confirm the CSS Entry File Has the Right Directives
Tailwind needs three layers injected into your main CSS file to function. With Tailwind v4, the syntax changed significantly — this is where most upgrade-related breakages happen.
Tailwind v4 (Current Standard)
@import "tailwindcss";
That single line replaces the old @tailwind base; @tailwind components; @tailwind utilities; directives. If you’re on v4 and still using the v3 directives, your build will either silently fail or throw a parse error.
Tailwind v3 (Legacy)
@tailwind base;
@tailwind components;
@tailwind utilities;
If you’ve upgraded to v4 but left the old directives in place, the PostCSS plugin won’t know what to do with them.
Quick diagnostic: Check your build output. If your compiled CSS file is essentially empty (a few hundred bytes or less), your directives aren’t being processed.
Step 3: Check Your PostCSS Configuration
PostCSS is the engine that transforms Tailwind directives into real CSS. If it isn’t configured to use the Tailwind plugin, nothing else matters.
Tailwind v4 PostCSS Config
Create or update postcss.config.js (or .mjs):
export default {
plugins: {
"@tailwindcss/postcss": {},
},
};
Tailwind v3 PostCSS Config
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};
Common pitfall: In v4, autoprefixer is no longer needed as a separate plugin — it’s built into the Tailwind PostCSS plugin. Having both can occasionally cause duplicate prefix output, though it won’t break your build.
Also check for a conflicting .postcssrc, postcss.config.json, or a postcss key inside package.json. Only one config source should be active. I once spent an hour debugging a project that had a postcss.config.js in the root and a postcss block in package.json — the root file was silently ignored.
Step 4: Validate Your Content Paths
This is the single most common cause of missing styles in Tailwind. The content array tells Tailwind which files to scan for class names. If a file isn’t listed, any classes used inside it won’t be generated.
Tailwind v3 Content Configuration
// tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
"./src/**/*.{html,js,jsx,ts,tsx,vue,svelte}",
"./public/index.html",
],
theme: {
extend: {},
},
plugins: [],
};
Tailwind v4 Content Configuration
v4 uses automatic content detection by default — it scans your project for files without needing an explicit content array. However, if you’re using a non-standard source directory, you may need to specify sources explicitly:
@import "tailwindcss" source(none);
@source "../src/**/*.{html,js,jsx,ts,tsx}";
@source "../components/**/*.{html,js,jsx,ts,tsx}";
Common Path Mistakes
-
Relative vs absolute paths: Paths are relative to the config file, not your project root. If your
tailwind.config.jslives infrontend/, then./srcrefers tofrontend/src. -
Missing extensions: Forgetting
.tsxwhen using TypeScript with React, or.vuefor Vue projects. -
Wrong glob syntax:
./src/**/*.html(recursive) vs./src/*.html(non-recursive). If your components live in nested folders, you need the recursive**. -
Ignoring third-party packages: If you use a component library built on Tailwind (like shadcn/ui or daisyUI), you may need to include its path:
content: [
"./src/**/*.{js,jsx,ts,tsx}",
"./node_modules/@my-org/ui/**/*.{js,jsx,ts,tsx}",
],
Step 5: Ensure the Build Process Is Running
Tailwind doesn’t work by magic — it needs a process watching your files and regenerating CSS when they change. Depending on your setup, there are several ways this can break.
Standalone Tailwind CLI
npx tailwindcss -i ./src/input.css -o ./dist/output.css --watch
If you forget the --watch flag, the CLI builds once and exits. Your styles will work until you edit a file, then they’ll go stale.
With a Bundler (Vite, Webpack, Rollup)
In bundler-based setups, PostCSS runs as part of the build pipeline. Make sure your dev server is actually running:
npm run dev
Check the terminal output for PostCSS or Tailwind errors — they often appear as warnings rather than fatal errors.
Next.js
Next.js 14+ has built-in Tailwind support, but it still needs the PostCSS plugin configured. If you’re using next dev and Tailwind isn’t working, verify that:
postcss.config.jsexists at the project rootapp/globals.css(or equivalent) imports Tailwind- You’re not accidentally importing CSS through a client component that isn’t rendered
Step 6: Check for CSS Source Order Issues
If some Tailwind classes work but others don’t, the problem might be CSS specificity. Tailwind utilities are designed to be low-specificity (single class selectors), so any custom CSS with higher specificity can override them.
This is a frequent issue when combining Tailwind with existing CSS frameworks:
/* This overrides Tailwind's bg-* utilities everywhere */
button {
background-color: #ccc !important;
}
Fix: Load your custom CSS before the Tailwind directives, or use Tailwind’s @layer to control specificity:
@layer base {
button {
background-color: #ccc;
}
}
Classes in @layer utilities will always win over @layer base, which is how Tailwind is designed to work.
Step 7: Verify Your Tailwind Version Compatibility
Tailwind v4 introduced breaking changes. If you’ve mixed v4 packages with v3 configs (or vice versa), things will break in subtle ways.
Check installed versions:
npm list tailwindcss
npm list @tailwindcss/postcss
If you see something like tailwindcss@4.0.1 but your config uses the v3 format, you need to either downgrade or migrate.
Migrating from v3 to v4
The official upgrade tool handles most of the heavy lifting:
npx @tailwindcss/upgrade
This automatically:
– Updates your package.json
– Converts tailwind.config.js settings to CSS-based configuration
– Updates PostCSS plugin references
– Adjusts custom theme definitions
After running it, review the generated changes carefully — especially custom plugins and theme extensions, which may need manual attention.
Step 8: Debug the Generated CSS Output
When nothing else works, looking at the actual compiled CSS is the fastest way to pinpoint the problem.
Inspecting Build Output
If you’re using the CLI:
npx tailwindcss -i ./src/input.css -o ./dist/output.css
cat ./dist/output.css | head -50
You should see CSS variables, utility classes, and base styles. If the file is nearly empty, your directives or content paths are wrong.
Browser DevTools
Open your browser’s developer tools, go to the Elements tab, and inspect an element that should have Tailwind styles. Check:
- Is the CSS file being loaded? (Check the Network tab for 404s)
- Are the utility classes present in the stylesheet?
- Are they being overridden by another rule? (Look for strikethrough text in the Styles panel)
If the class names exist in the CSS file but aren’t applying, the issue is specificity or source order. If they don’t exist at all, the issue is content detection or the build process.
Step 9: Check for Syntax Errors in Your Config
A syntax error in tailwind.config.js will silently break the entire build. JavaScript doesn’t always throw a helpful error for config issues.
Common mistakes:
// Wrong: trailing comma in theme object (pre-ES2017 Node)
theme: {
extend: {
colors: {
primary: '#3b82f6',,
},
},
}
// Wrong: missing closing brace
module.exports = {
content: ["./src/**/*.{html,js}"],
theme: {
extend: {},
}
Validate your config by requiring it in a Node REPL:
node -e "console.log(require('./tailwind.config.js'))"
If this throws an error, you’ve found your problem.
Step 10: Edge Cases and Uncommon Issues
If you’ve made it this far and Tailwind still isn’t working, one of these less obvious causes might be at play.
Browser Caching
Browsers aggressively cache CSS files. After a rebuild, your old stylesheet might still be served. Try:
- Hard refresh:
Ctrl+Shift+R(Windows/Linux) orCmd+Shift+R(Mac) - Disabling cache in DevTools (Network tab → “Disable cache”)
- Adding a cache-busting query parameter to your CSS link
VS Code Extension Conflicts
The official Tailwind CSS IntelliSense extension is excellent, but it can cause confusion. If you see autocomplete suggestions and IntelliSense highlighting but no actual styles, the extension is working — your build process isn’t.
Conversely, if the extension shows “No utility classes found,” it can’t locate your Tailwind config. Check the extension settings:
{
"tailwindCSS.experimental.configFile": "./src/tailwind.config.js"
}
Node Version Incompatibility
Tailwind v4 requires Node.js 18 or later. Check your version:
node --version
If you’re on Node 16 or lower, upgrade using nvm:
nvm install 20
nvm use 20
Dynamic Class Construction
Tailwind’s content scanner looks for complete class strings. It doesn’t evaluate JavaScript, so dynamically constructed class names won’t be detected:
// ❌ Won't work — Tailwind can't see these class names
const color = "blue";
<div className={`bg-${color}-500`}>Hello</div>
// ✅ Works — full class names are visible
const colors = {
blue: "bg-blue-500",
red: "bg-red-500",
};
<div className={colors[color]}>Hello</div>
This is one of the most common “Tailwind is broken” reports from React and Vue developers. The fix is to always use complete class name strings, even if it means maintaining a mapping object.
Content Security Policy (CSP) Blocking Styles
If your app uses a strict Content Security Policy, inline styles and dynamically injected stylesheets might be blocked. Check your browser console for CSP violation messages.
Add 'unsafe-inline' to your style-src directive, or use a nonce-based approach for production:
Content-Security-Policy: style-src 'self' 'nonce-<random>';
Mono-Repo Path Issues
In a Turborepo or Nx workspace, Tailwind configs often live in a shared package. Make sure paths are relative to the config file location, not the consuming app:
// packages/ui/tailwind.config.js
content: [
"./src/**/*.{js,jsx,ts,tsx}",
// Scan consuming apps too
"../../apps/*/src/**/*.{js,jsx,ts,tsx}",
],
Third-Party Plugin Conflicts
Some PostCSS plugins conflict with Tailwind. If you’ve recently added a plugin like cssnano, purgecss, or css-modules, try disabling it temporarily to isolate the issue:
module.exports = {
plugins: {
"@tailwindcss/postcss": {},
// Try commenting these out one at a time
// cssnano: {},
},
};
macOS Case-Sensitivity
macOS uses a case-insensitive filesystem by default, but Linux (and most CI/CD environments) is case-sensitive. If your config references ./Src but the folder is actually ./src, it works locally but fails in production. Always match exact casing.
Prevention Tips: Setting Up Tailwind the Right Way
A few habits will save you from future debugging sessions:
1. Use a Consistent Project Structure
Keep your Tailwind config, PostCSS config, and CSS entry file in predictable locations. A structure like this works across most frameworks:
project/
├── postcss.config.js
├── tailwind.config.js (v3 only)
├── src/
│ ├── styles/
│ │ └── globals.css
│ └── components/
2. Add a Sanity Check Early
When setting up Tailwind, add a test element immediately:
<div class="bg-red-500 text-white p-4">
If this is red, Tailwind is working.
</div>
This gives you a visible confirmation before you build out your entire UI.
3. Pin Your Versions
Avoid latest or * in your dependencies:
{
"devDependencies": {
"tailwindcss": "4.0.1",
"@tailwindcss/postcss": "4.0.1"
}
}
This prevents surprise breakages when a new major version ships.
4. Use the Official Setup Tools
Framework-specific starters are pre-configured and tested:
# Vite + Tailwind
npm create vite@latest my-app -- --template react
cd my-app
npm install
npx tailwindcss init -p
# Next.js (Tailwind included by default)
npx create-next-app@latest my-app
5. Keep Dependencies Updated
Run npm audit and npm outdated regularly. Outdated PostCSS or Autoprefixer versions can cause subtle compatibility issues.
Framework-Specific Quick Fixes
Next.js
If Tailwind isn’t working in a Next.js project:
- Ensure
app/globals.cssimports Tailwind - Verify
postcss.config.mjsuses the right plugin - Check that
globals.cssis imported in your root layout:
import './globals.css';
export default function RootLayout({ children }) {
return (
<html lang="en">
<body>{children}</body>
</html>
);
}
Vite
For Vite projects, make sure @tailwindcss/postcss (v4) or tailwindcss (v3) is in your PostCSS config, and that your CSS file is imported in your entry point:
// main.tsx
import './index.css';
React (Create React App)
CRA has known issues with Tailwind due to its locked PostCSS configuration. The recommended approach is to eject or use craco/`react-app-rewired