Tailwind CSS - Content Configuration


Tailwind CSS Content Configuration specifies sources for the project. The Content section of the 'tailwind.config.js' file specifies all the HTML templates, Javascript components, and any other source files that contain Tailwind class names.

Tailwind CSS config.js

Content Source Path Configuration

The configuration of the source path in the content section of the 'tailwind.config.js' file helps Tailwind CSS scan all the HTML, Javascript components, and any other files containing class names to generate the corresponding CSS for those styles.

/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    './pages/**/*.{html,js}',
    './components/**/*.{html,js}'
  ],
  // ...
}

Key Points

The key points to remember while configuring Content in Tailwind CSS.

  • Use glob patterns (**/*) to match files recursively.
  • Use {} with comma-separated values to match a list of options like {html,js}.
  • Keep paths relative to your project root.

Content Configuration Pattern Tips

For effective configuration of the content, follow these tips:

  • Be precise: Exclude broad patterns that capture unnecessary files or directories, such as node_modules.
content: [
'./components/**/*.{html,js}',
'./pages/**/*.{html,js}',
'./index.html',  // Include specific files if needed
],
    
  • Involve Entry Points: Make sure your Tailwind setup includes the main HTML file, usually located at public/index.html.
  • content: [
    './public/index.html',
    './src/**/*.{html,js}',
    ],
    
  • Javascript Files: Include any JS files that add classes to your HTML.
  • content: [
    './src/**/*.js',
    ],
        
  • Exclude CSS File: Never include CSS files in your content configuration.
  • content: [
    './src/**/*.css',
    ],
        

    Deep Class Identification

    Tailwind uses regular expressions to extract potential class names from the source code, without parsing or executing it.

    <div class="md:flex">
      <div class="md:flex-shrink-0">
        <img class="rounded-lg md:w-56" src="/img/shopping.jpg" alt="Woman paying for a purchase">
      </div>
      <div class="mt-4 md:mt-0 md:ml-6">
        <div class="uppercase tracking-wide text-sm text-indigo-600 font-bold">
          Marketing
        </div>
        <a href="/get-started" class="block mt-1 text-lg leading-tight font-semibold text-gray-900 hover:underline">
          Finding customers for your new business
        </a>
        <p class="mt-2 text-gray-600">
          Getting a new business off the ground is a lot of hard work.
          Here are five ideas you can use to find your first customers.
        </p>
      </div>
    </div>
    

    Note: Tailwind works with any language, like JSX, by searching for classes everywhere, not just in HTML.

    Dynamic Class Names

    Tailwind only finds whole class names in your code. If you build class names using strings or parts. Tailwind won't recognize them and won't generate the corresponding CSS.

    Measures to Follow When Creating Class Names.

    • Always use complete class names, instead constructing class names dynamically.
    <div class="{{ error ? 'text-red-600' : 'text-green-600' }}"></div>
        
  • Always map props to static class names, instead of using props to dynamically construct classes.
  • function Button({ color, children }) {
      const colorVariants = {
        blue: "bg-blue-600 hover:bg-blue-500",
        red: "bg-red-600 hover:bg-red-500",
      };
    
      return <button className={`${colorVariants[color]} ...`}>{children}</button>;
    }
        

    Using External Libraries

    When working with third party libraries and styling that with your own custom CSS, try to not write those styles without using Tailwind's @layer feature. This will make it easier for tailwind to scan the source code of a third party library.

    @tailwind base;
    @tailwind components;
    
    .select2-dropdown {
        @apply rounded-b-lg shadow-md;
    }
    .select2-search {
        @apply border border-gray-300 rounded;
    }
    .select2-results__group {
        @apply text-lg font-bold text-gray-900;
    }
    /* ... */
    
    @tailwind utilities;
    

    If you are using Tailwind-styled components in multiple projects, make sure you have configure Tailwind to scan them for class names.

    module.exports = {
        content: [
            './components/**/*.{html,js}',
            './pages/**/*.{html,js}',
            './node_modules/@my-company/tailwind-components/**/*.js',
        ],
        // ...
        }
    

    If you're using a monorepo with workspaces, you may need to use require.resolve so that Tailwind can find your content files.

    const path = require('path');
    
    module.exports = {
        content: [
        './components/**/*.{html,js}',
        './pages/**/*.{html,js}',
        path.join(path.dirname(require.resolve('@my-company/tailwind-components')), '**/*.js'),
        ],
        // ...
    }
    

    Using Relative Path

    Tailwind uses the current directory for paths by default. To avoid issues, set the 'relative' property to 'true' to tie paths to the 'tailwind.config.js' file.

    module.exports = {
      content: {
        relative: true,
        files: ["./pages/**/*.{html,js}", "./components/**/*.{html,js}"],
      },
      // ...
    };
    

    Setting Raw Content

    To scan raw content instead of a file's contents in Tailwind, use an object with a "raw" key instead of a file path. This allows you to configure Tailwind to scan custom content.

    /** @type {import('tailwindcss').Config} */
    module.exports = {
        content: [
        './pages/**/*.{html,js}',
        './components/**/*.{html,js}',
        { raw: '<div class="font-bold">', extension: 'html' },
        ],
        // ...
    }
    

    Safelisting Classes

    If you want Tailwind to generate certain class names that don't exist in your content files, use the safelist option.

    /** @type {import('tailwindcss').Config} */
    module.exports = {
        content: [
        './pages/**/*.{html,js}',
        './components/**/*.{html,js}',
        ],
        safelist: [
        'bg-red-500',
        'text-3xl',
        'lg:text-4xl',
        ]
        // ...
    }
    

    Using Regular Expressions

    Tailwind supports pattern-based safelisting for situations where you need to safelist many classes.

    /** @type {import('tailwindcss').Config} */
    module.exports = {
      content: [
        './pages/**/*.{html,js}',
        './components/**/*.{html,js}',
      ],
      safelist: [
        'text-2xl',
        'text-3xl',
        {
          pattern: /bg-(red|green|blue)-(100|200|300)/,
        },
      ],
      // ...
    }
    

    You can force Tailwind to create extra styles for certain classes by adding them to the 'variants' option.

    /** @type {import('tailwindcss').Config} */
    module.exports = {
      content: [
        './pages/**/*.{html,js}',
        './components/**/*.{html,js}',
      ],
      safelist: [
        'text-2xl',
        'text-3xl',
        {
          pattern: /bg-(red|green|blue)-(100|200|300)/,
          variants: ['lg', 'hover', 'focus', 'lg:hover'],
        },
      ],
      // ...
    }
    

    Eliminating Classes

    Tailwind might create unnecessary classes, like generating the 'container' class even if it's not used, as shown below.

    <div class="text-lg leading-8 text-gray-600">
      Every custom pool we design starts as a used shipping container, and is
      retrofitted with state of the art technology and finishes to turn it into
      a beautiful and functional way to entertain your guests all summer long.
    </div>
    

    To avoid conflicts with existing CSS without prefixing all Tailwind classes, use the blocklist option to ignore specific classes.

    /** @type {import('tailwindcss').Config} */
    module.exports = {
        content: [
        './pages/**/*.{html,js}',
        './components/**/*.{html,js}',
        ],
        blocklist: [
        'container',
        'collapse',
        ],
        // ...
    }
    

    Source Files Transformation

    If you write content that turns into HTML (like Markdown), convert content to HTML first before extracting classes. Use 'content.transform' to convert files and specify source paths with 'content.files'.

    const remark = require('remark')
    
    module.exports = {
      content: {
        files: ['./src/**/*.{html,md}'],
        transform: {
          md: (content) => {
            return remark().process(content)
          }
        }
      },
      // ...
    }
    

    Modifying Extraction Logic

    Use 'extract' to customize class name detection for specific file types.

    Note: This is an advanced feature, and you'll need to specify source paths differently.

    /** @type {import('tailwindcss').Config} */
    module.exports = {
      content: {
        files: ['./src/**/*.{html,wtf}'],
        extract: {
          wtf: (content) => {
            return content.match(/[^<>"'`\s]*/g)
          }
        }
      },
      // ...
    }
    

    Troubleshooting Common Issues

    The following are some common issues generated while configuring content in Tailwind CSS, along with measures to avoid them.

    • Missing Classes: If Tailwind isn't generating classes, double-check your content configuration and file extensions (e.g., 'jsx' instead of 'js' for React components) to ensure it matches all source files.
    module.exports = {
        content: [
            './src/**/*.{html,js}',
            './src/**/*.{html,js,jsx}'
        ],
        // ...
    }
    
  • Dynamic Class Names: Tailwind doesn't support dynamic class name construction.
  • <!-- Incorrect -->
    <div class="text-{{ error ? 'red' : 'green' }}-600"></div>
    
    <!-- Correct -->
    <div class="{{ error ? 'text-red-600' : 'text-green-600' }}"></div>
        
  • Infinite Styles Rebuild: Ensure your build tool supports glob patterns correctly.
  • content: [
    './src/**/*.{html,js}',
    './src/pages/**/*.{html,js}',
    './src/components/**/*.{html,js}',
    './src/index.html',
    ], 
    
  • Output Issues: It might not support PostCSS, causing problems. Try Tailwind CLI to compile CSS separately and avoid integration issues.
  • // package.json
    {
        // ...
        "scripts": {
        "start": "concurrently \"npm run start:css\" \"react-scripts start\"",
        "start:css": "tailwindcss -o src/tailwind.css --watch",
        "build": "npm run build:css && react-scripts build",
        "build:css": "NODE_ENV=production tailwindcss -o src/tailwind.css -m",
        },
    }