Skip to content

Tailwind CSS Optimization — Production Builds and Performance

DodaTech Updated 2026-06-28 5 min read

In this tutorial, you will learn about Tailwind CSS Optimization. We cover key concepts, practical examples, and best practices to help you master this topic.

Tailwind CSS optimization focuses on the JIT engine's on-demand generation, proper content path configuration, CSS Minification, and build Strategy to achieve production bundles under 10KB gzipped.

What You'll Learn

You will learn how the JIT engine works, configure content paths for effective purging, optimize build time, reduce CSS bundle size, and troubleshoot optimization issues.

Why It Matters

Unoptimized Tailwind can generate megabytes of CSS. DodaTech's production CSS is under 8KB gzipped through proper JIT configuration, enabling fast page loads for Doda Browser and Durga Antivirus Pro.

Real-World Use

The DodaTech tutorial site uses Tailwind's JIT engine with content paths targeting only template and markdown files, producing a 6.2KB production CSS bundle.

flowchart LR
    A[Components] --> B[Optimization]
    B --> C[JIT Engine]
    B --> D[Content Paths]
    B --> E[Minification]
    B --> F[Bundle Size]
    B --> G[Analysis]
    style B fill:#38bdf8,stroke:#0284c7,color:#fff
    style C fill:#22c55e,stroke:#16a34a,color:#fff

JIT Engine Basics

Tailwind v3 uses a Just-In-Time compiler that generates CSS only for the classes you actually use:

// tailwind.config.js - JIT is the default in v3+
module.exports = {
  content: [
    './pages/**/*.{js,jsx,ts,tsx,mdx}',
    './components/**/*.{js,jsx,ts,tsx}',
    './app/**/*.{js,jsx,ts,tsx}',
  ],
  // No purge or mode option needed - JIT is automatic
}

Expected output: Tailwind scans the specified files and generates only the utility classes it finds. Unused classes do not appear in the output.

Content Path Configuration

// tailwind.config.js
module.exports = {
  content: [
    // Include all template sources
    './index.html',
    './src/**/*.{js,ts,jsx,tsx}',
    './src/**/*.html',

    // Include markdown files (for documentation sites)
    './content/**/*.md',
    './docs/**/*.{md,mdx}',

    // Include PHP/Blade if using Laravel
    './resources/**/*.blade.php',
    './resources/**/*.php',

    // Include template literals with class names
    './src/**/*.js', // catches className={`...`}
  ],
}

Expected output: Tailwind scans all specified paths and generates classes found anywhere in the project's templates.

Class Detection Limitations

<!-- Classes detected correctly -->
<div class="bg-blue-500 text-white p-4">Detected</div>

<!-- Classes NOT detected (dynamic construction) -->
<div class={`bg-${color}-500`}>NOT detected</div>
<div class={['bg-blue', 'text-white'].join(' ')}>NOT detected</div>

<!-- Solution: use full class names -->
<div class={`${isActive ? 'bg-blue-500' : 'bg-gray-100'} text-white p-4`}>Detected</div>

<!-- Solution: use safelist -->

Expected output: Tailwind only detects complete, literal class names. Dynamic class construction requires safelist configuration.

Safelist for Dynamic Classes

// tailwind.config.js
module.exports = {
  content: ['./src/**/*.{js,jsx}'],
  safelist: [
    // Exact classes
    'bg-red-500',
    'bg-green-500',
    'bg-blue-500',

    // Patterns (regex)
    {
      pattern: /bg-(red|green|blue)-(100|200|300)/,
      variants: ['hover', 'focus'],
    },

    // All variants of a utility
    {
      pattern: /text-(sm|base|lg)/,
    },
  ],
}

Expected output: The safelisted classes (both exact and pattern-matched) are always included in the output, regardless of whether they appear in the scanned content.

Production Build Configuration

// tailwind.config.js
module.exports = {
  content: ['./src/**/*.{js,jsx}'],

  // Disable unused core plugins
  corePlugins: {
    container: false,    // If not using container
    float: false,        // If not using floats
    clear: false,        // If not using clear
    objectFit: false,    // If not using object-fit
    objectPosition: false,
  },
}
# Production build with PostCSS + CSSNano
npm run build

# Or with Tailwind CLI
npx @tailwindcss/cli -i input.css -o output.css --minify

Expected output: A production CSS file containing only used classes, minified and optimized, typically under 10KB gzipped.

Build Performance Tips

// tailwind.config.js
module.exports = {
  content: ['./src/**/*.{js,jsx}'],

  // Improve build speed
  future: {
    hoverOnlyWhenSupported: true, // Reduces hover variant generation
  },

  // Limit variant generation
  variants: {
    extend: {
      backgroundColor: ['hover', 'focus'],
      textColor: ['hover', 'focus'],
    },
  },
}
# Watch mode for development (fast rebuilds)
npx @tailwindcss/cli -i input.css -o output.css --watch

# Cache for faster rebuilds (PostCSS)
# Cache is stored in node_modules/.cache/tailwindcss

Expected output: Faster build times by limiting unnecessary variant generation and leveraging the JIT engine's incremental compilation.

Analyzing Bundle Size

# Use the Tailwind CLI with --analyze flag
# Or use a bundle analyzer with PostCSS
npm install -D @fullhuman/postcss-purgecss

# Check output CSS size
wc -c output.css
gzip -c output.css | wc -c

Expected output: Analysis shows which classes are included and the final bundle size. Typically 3-10KB gzipped for a production site.

Common Mistakes

1. Missing Content Paths

If content paths do not cover all template files, needed classes are missing and styles break silently.

2. Dynamic Class Construction

Building class names with string concatenation (bg-${color}-500) prevents JIT detection. Use full class names or safelist.

3. Not Regenerating After Content Changes

Tailwind regenerates based on file watcher. If watcher is not running, new classes do not appear. Always run build on deploy.

4. Keeping Source Maps in Production

Source maps bloat the CSS output. Disable them in production: --no-source-map with CLI or configure in PostCSS.

5. Ignoring PurgeCSS Config

While JIT replaces PurgeCSS, misconfigured content paths can still cause missing classes. Use the same content array approach.

Practice Questions

  1. How does Tailwind's JIT engine work? It scans content files, detects used class names, and generates only those classes on-demand.

  2. What happens if a class is constructed dynamically? JIT cannot detect it. Use the safelist option or keep class names as complete strings.

  3. How small should a production CSS file be? Typically 3-10KB gzipped. Anything over 20KB suggests unused classes or over-generous content paths.

  4. What is the safelist option for? To include classes that Tailwind cannot detect (dynamic names, classes added by third-party libraries).

  5. How do you disable unused core plugins? Set them to false in corePlugins: corePlugins: { container: false }.

Challenge

Audit a Tailwind project: check content paths cover all templates, identify dynamic class construction, measure bundle size (gzipped), configure safelist for known dynamic patterns, and reduce core plugin usage.

FAQ

What is the difference between JIT and AOT?

JIT (Just-In-Time) generates CSS on-demand during development and production. AOT (Ahead-Of-Time) pre-generates everything. JIT is default in v3+.

Does JIT work with CDN?

CDN loads the full Tailwind CSS. JIT only works with build tools. For production, always use the JIT build.

How do I debug missing classes?

Check the content path coverage. Check for dynamic class construction. Use the safelist. Verify the class is not a typo.

Can I use JIT with multiple configs?

Yes. Each CSS file with @config uses its own content paths and safelist for independent JIT compilation.

Does JIT increase build time?

Development builds are faster (incremental). Production builds scan all content but generate far less CSS than the old AOT approach.

Mini Project

Set up a Tailwind project with: comprehensive content paths covering HTML, JSX, and markdown files. Configure safelist for 3 dynamic color patterns. Build production CSS and verify bundle size under 10KB gzipped.

What's Next

Apply all Tailwind skills in the Tailwind Project capstone. Build a complete, production-optimized website using everything covered in this course.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro