Search code examples
next.jstailwind-css

NextJS - Most Tailwind classes work... but not all


I have this weird case where classes like w-1/2 work, but w-1/3 wont, despite being documented.

This is my code:

<thead>
  <tr>
    <th class="px-5 py-3 border-b-2 border-gray-300 bg-gray-100 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider w-1/4">Invoice Number</th>
    <th class="px-5 py-3 border-b-2 border-gray-300 bg-gray-100 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider w-1/4">Customer</th>
    <th class="px-5 py-3 border-b-2 border-gray-300 bg-gray-100 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider w-1/4">Status</th>
    <th class="px-5 py-3 border-b-2 border-gray-300 bg-gray-100 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider w-1/4">Amount Due</th>
    <th class="px-5 py-3 border-b-2 border-gray-300 bg-gray-100 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider w-1/4">Actions</th>
  </tr>
</thead>

I know that they are not even being applied looking at the dev tools.

enter image description here

Checking the CSS file on .next/static/css/ I can also see that the class is missing.

enter image description here

I am not sure what to do anymore. Here are the relevant config files.

package.json

{
  "name": "biller",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint"
  },
  "dependencies": {
    "js-cookie": "^3.0.5",
    "next": "14.0.4",
    "react": "^18",
    "react-dom": "^18"
  },
  "devDependencies": {
    "autoprefixer": "^10.0.1",
    "eslint": "^8",
    "eslint-config-next": "14.0.4",
    "postcss": "^8",
    "tailwindcss": "^3.3.0"
  }
}

tailwind.config.js

/** @type {import('tailwindcss').Config} */
module.exports = {
    content: [
        './src/pages/**/*.{js,ts,jsx,tsx,mdx}',
        './src/components/**/*.{js,ts,jsx,tsx,mdx}',
        './src/app/**/*.{js,ts,jsx,tsx,mdx}',
        './src/context/**/*.{js,ts,jsx,tsx,mdx}',
        './src/utils/**/*.{js,ts,jsx,tsx,mdx}',
        './src/hooks/**/*.{js,ts,jsx,tsx,mdx}',
    ],
    theme: {
        extend: {},
    },
    plugins: [],
};

All the paths inside my src folder are covered, so that cannot be it.

UPDATE

I figured out part of it. Apparently it is due to the fact that I am not "hardcoding" the way that the class render on the JSX, but instead I am doing this:

// "witdth" prop is optional. Can have values like "1/2", "1/3", "1/4", etc.
export const TH = ({ children, width }) => {
    const widthClass = width ? `w-${width}` : '';
    return (
        <th
            className={`px-5 py-3 border-b-2 border-gray-300 bg-gray-100 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider ${widthClass}`}
        >
            {children}
        </th>
    );
};

Apparently it will only be included if it is hardcoded. This sucks... is there a way to prevent this??


Solution

  • Problem

    Tailwind includes only the explicitly used and discoverable classes in your final CSS file. The reason behind this is to minimize the file size as much as possible.

    Tailwind is unable to dynamically map classes that are not pre-defined in advance.

    Safelist in TailwindCSS v3

    You can use a safelist to ensure that certain classes are always included in the final CSS code.

    tailwind.config.js

    export default {
      safelist: [
        // can list them individually
        'w-1/2',
        'w-1/3',
        // or can create a more comprehensive rule as well
        {
          pattern: /^w-1\/\d+$/, // The regex written by @Wongjn can be perfect
        },
      ],
    }
    

    Safelist until TailwindCSS v4

    The corePlugins, safelist and separator options from the JavaScript-based config are not supported in v4.0.


    Source: Use the @config directive to load a legacy JavaScript-based configuration