cssnext.jstailwind-csspostcsstailwind-css-4

Tailwind 4 Utilities Failing ("Cannot apply unknown utility class") in Next.js 15 (Pages Router) Build


I'm setting up a new project using Next.js (v15.3.0 - Pages Router) and Tailwind CSS (v4.1.4) and I've hit a persistent build issue where Tailwind utility classes are not being recognized.

The Core Problem:

The Next.js development server (next dev) fails to compile, throwing errors like:

Error: Cannot apply unknown utility class: bg-gray-50

Initially, this happened for default Tailwind classes (bg-gray-50) used with @apply in my globals.css. After trying different configurations in globals.css (like using @import "tailwindcss/preflight"; @reference "tailwindcss/theme.css";), the error shifted to my custom theme colors:

Error: Cannot apply unknown utility class: text-primary-600

When trying to use the theme() function directly in @layer base, I get:

Error: Could not resolve value for theme function: theme(colors.gray.50).

Essentially, it seems the PostCSS/Tailwind build process isn't recognizing or applying any Tailwind utility classes correctly within the CSS build pipeline.

Relevant Versions:

Configuration Files:

tailwind.config.js (Simplified attempt):

const defaultTheme = require('tailwindcss/defaultTheme');
const colors = require('tailwindcss/colors');

module.exports = {
  content: [
    "./src/pages/**/*.{js,ts,jsx,tsx}",
    "./src/components/**/*.{js,ts,jsx,tsx}",
  ],
  theme: { // No 'extend'
    fontFamily: {
      sans: ['Inter', ...defaultTheme.fontFamily.sans],
    },
    colors: {
      transparent: 'transparent',
      current: 'currentColor',
      black: colors.black,
      white: colors.white,
      gray: colors.gray, // Explicitly included
      red: colors.red,
      green: colors.green,
      primary: { // My custom color
        DEFAULT: '#2563EB',
        // ... other shades 50-950
        600: '#2563EB',
        700: '#1D4ED8',
      },
      secondary: { /* ... custom secondary color ... */ },
    },
     ringOffsetColor: {
        DEFAULT: '#ffffff',
     },
  },
  plugins: [],
};

postcss.config.js:

module.exports = {
  plugins: {
    "@tailwindcss/postcss": {}, // Using the v4 specific plugin
    autoprefixer: {},
  },
};

src/styles/globals.css (Latest attempt):

/* src/styles/globals.css */
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap');

@import "tailwindcss/preflight";
@tailwind theme;
@tailwind utilities;

@layer base {
    html {
        font-family: 'Inter', sans-serif;
        scroll-behavior: smooth;
    }

    body {
        @apply bg-gray-50 text-gray-900 antialiased;
    }

    a {
        @apply text-primary-600 hover:text-primary-700 transition-colors duration-150;
    }
}

Troubleshooting Steps Attempted (Without Success):

Despite these steps, the build consistently fails, unable to recognize or process Tailwind utility classes referenced in CSS (especially within globals.css). Standard utility classes used directly on JSX elements (e.g., <div className="p-4 bg-primary-500">) also fail to apply styles correctly because the underlying CSS isn't generated properly.

Has anyone encountered similar issues with this specific stack (Next.js 15 / Tailwind 4 / Pages Router)? What could be causing this fundamental breakdown in Tailwind's processing within the Next.js build? Any configuration nuances I might be missing?

Thanks in advance for any insights!


Solution

  • Since TailwindCSS v4, TailwindCSS needs to be imported differently. Due to incorrect import, your classes didn't exist, so you couldn't use them. This is how it should look correctly:

    @import "tailwindcss";
    
    @layer base {
      html {
        font-family: 'Inter', sans-serif;
        scroll-behavior: smooth;
      }
    
      body {
        @apply bg-gray-50 text-gray-900 antialiased;
      }
    
      a {
        @apply text-primary-600 hover:text-primary-700 transition-colors duration-150;
      }
    }
    

    In addition, starting from v4, the default usage of tailwind.config.js has been discontinued. The file itself is no longer necessary, as a CSS-first configuration has been introduced. You can read more about it here:

    There have indeed been many breaking changes that even AI models haven't fully kept up with. It's worth going through the StackOverflow and TailwindCSS resources regarding this. A lot of guides, videos, and documentation created for TailwindCSS v3 have become outdated in v4.

    CSS-first configuration based on your tailwind.config.js

    @import "tailwindcss";
    
    @theme {
      /* Font families */
      --font-sans: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont,
                   "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif,
                   "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
    
      /* Colors */
      --color-transparent: transparent;
      --color-current: currentColor;
      /* There's no need to declare black, white, gray, red, or green — they're included in TailwindCSS by default */
      /* Primary color */
      --color-primary-600: #2563EB;
      --color-primary-700: #1D4ED8;
      --color-primary: #2563EB;
      /* Secondary color */
      --color-secondary: #FACC15; /* Example: yellow-400, adjust to your desired value */
    
      /* Ring offset */
      --ring-offset-color: #ffffff;
    }
    
    @layer base {
      html {
        font-family: 'Inter', sans-serif;
        scroll-behavior: smooth;
      }
    
      body {
        @apply bg-gray-50 text-gray-900 antialiased;
      }
    
      a {
        @apply text-primary-600 hover:text-primary-700 transition-colors duration-150;
      }
    }
    

    Related:

    There's no need to declare default colors - as you did in your tailwind.config.js - unless you want to override them. If you're fine with the default values, you don't need to declare anything.

    If you want to remove a default color (e.g., green), you can do so like this:

    --color-green-*: initial;
    

    This will remove utilities like text-green-500, etc.

    However, note that text-green-500 and similar classes aren't included in the compiled CSS unless you actually use them in your code - so removing them manually often isn't necessary.