Tailwind Classes Not Applying in Laravel Blade

The problem: Tailwind classes work perfectly with npm run dev, but after npm run build and deploying, half your styling disappears — no console error, no crash, just plain unstyled HTML.

Environment: Laravel 11.x, Tailwind CSS 3.x, Vite, Blade templates, deployed via standard npm run build in CI.

The Error

There's no exception here — that's exactly what makes this one annoying. The build succeeds cleanly and silently produces a much smaller CSS file than expected:

▲ terminal
$ npm run build

vite v5.2.0 building for production...
✓ 38 modules transformed.
public/build/assets/app-3f7a1c2e.css   4.12 kB │ gzip: 1.10 kB
public/build/assets/app-9d2e5b41.js   62.48 kB │ gzip: 22.9 kB
✓ built in 812ms

// expected app.css around 18-25kB with the full utility set —
// 4kB means Tailwind only found a handful of classes to keep

[SCREENSHOT NEEDED: production page in browser devtools, showing a Blade element with class="bg-blue-600 rounded-lg px-4 py-2" in the Elements panel but no matching rule in the Computed/Styles panel]

Why It Happens

Tailwind doesn't ship every utility class by default — it scans your project files listed in the content array of tailwind.config.js, finds which class names you actually use, and generates CSS only for those. In dev mode with the Vite plugin, this scan re-runs on every file save, so it's forgiving. In a production build, it scans once, and if a file containing your classes isn't in that content array, those classes are simply never generated — not broken, just never written.

This almost always comes down to one of these:

  1. New Blade view directories added after the initial Tailwind setup (like resources/views/livewire/ or resources/views/components/) that were never added to content.
  2. Classes built dynamically with string concatenation in PHP or Blade, like class="text-{{ $color }}-500" — Tailwind's scanner only sees literal strings, so it never generates text-red-500, text-blue-500, etc. from a variable.
  3. Vendor or package Blade views (from a UI package or admin panel) that render Tailwind classes but live outside resources/views entirely.

The Fix

Check your content array first — it needs to cover every file that contains a Tailwind class name, not just your main Blade folder:

content: [
    './resources/views/*.blade.php',  // too narrow — misses subfolders
    './resources/views/**/*.blade.php',
    './resources/js/**/*.{js,jsx,ts,tsx,vue}',
    './app/View/Components/**/*.php',
],

For dynamic class names, Tailwind's scanner can't see variables — you have to give it the full literal class string somewhere it can find it. Use a lookup map instead of concatenation:

<div class="text-{{ $color }}-500">  // scanner can't see this

// in a helper or Blade component method:
$classes = [
    'red' => 'text-red-500',
    'blue' => 'text-blue-500',
];
<div class="{{ $classes[$color] }}">

After fixing the config, clear caches and rebuild — a stale view cache can keep serving old compiled Blade output even after your CSS is regenerated:

$ php artisan view:clear
$ npm run build

Step-by-Step

  1. Run npm run build and check the resulting CSS file size — if it's a few KB instead of the usual 15-25KB, Tailwind is under-scanning your project.
  2. Open tailwind.config.js and confirm the content array uses **/*.blade.php (with the double-star glob) so it recurses into subfolders like livewire/ and components/.
  3. Search your codebase for any Blade class attribute built with {{ }} interpolation directly inside a class string — those are invisible to Tailwind's scanner.
  4. Replace dynamic class construction with a PHP lookup array or match expression that contains the full literal class names.
  5. Add any package or vendor view paths (admin panels, third-party components) that render Tailwind classes to the content array explicitly.
  6. Run php artisan view:clear then rebuild, and confirm the CSS file size jumps back up before redeploying.
⚠ Edge case: if you're using a component library or CMS that stores class names in the database (e.g. a page builder letting editors type raw Tailwind classes into a CMS field), no content glob can catch those at build time — the classes don't exist in any file Tailwind scans. The usual fix is a safelist array in tailwind.config.js listing those specific classes explicitly, so they're always generated regardless of whether Tailwind's scanner can "see" them.

Still missing styles after checking your config? Send me your tailwind.config.js on the Contact page and I'll take a look.

Advertisement
Advertisement