Optimize Tailwind CSS with Claude Code

Written by Michael Lip · Solo founder of Zovo · $400K+ on Upwork · 100% JSS Join 50+ builders · More at zovo.one

The Problem

Your Tailwind CSS setup has issues: the production CSS bundle is too large, you have duplicate utility classes scattered across components, class strings are unreadable at 200+ characters, and there is no consistent design system. Some components use px-4 while others use px-[17px], and nobody can remember which colors are official brand colors versus one-off choices.

Quick Start

Ask Claude Code to audit your Tailwind usage:

Audit my Tailwind CSS usage across the codebase:
1. Find classes that are defined but never used in templates
2. Find arbitrary values (px-[17px]) that should be design tokens
3. Find duplicated class patterns that should be extracted to components
4. Check the production CSS bundle size
5. Verify the purge/content configuration covers all template files

What’s Happening

Tailwind CSS generates utility classes on demand based on what it finds in your source files. The content configuration tells Tailwind which files to scan. If misconfigured, Tailwind either includes too many classes (large bundles) or misses classes used in dynamic expressions (broken styles).

Beyond configuration, Tailwind projects accumulate technical debt: long class strings, inconsistent spacing, arbitrary values instead of design tokens, and duplicated patterns. Claude Code can systematically clean all of these.

Step-by-Step Guide

Step 1: Fix the content configuration

Ask Claude Code to verify your Tailwind configuration scans all template files:

// tailwind.config.ts
import type { Config } from 'tailwindcss';

const config: Config = {
  content: [
    './src/**/*.{js,ts,jsx,tsx,mdx}',
    './components/**/*.{js,ts,jsx,tsx}',
    './app/**/*.{js,ts,jsx,tsx,mdx}',
    // Don't forget these common locations:
    './pages/**/*.{js,ts,jsx,tsx}',
    './layouts/**/*.{js,ts,jsx,tsx}',
  ],
  theme: {
    extend: {},
  },
  plugins: [],
};

export default config;

Common mistakes Claude Code will catch:

// Wrong: missing MDX files
content: ['./src/**/*.{js,ts,jsx,tsx}'],
// Missing: './src/**/*.mdx'

// Wrong: missing component library
content: ['./app/**/*.tsx'],
// Missing: './node_modules/@myorg/ui/**/*.{js,ts,jsx,tsx}'

// Wrong: content path doesn't match project structure
content: ['./pages/**/*.tsx'],
// Actual files are in ./src/pages/

Step 2: Establish a design token system

Ask Claude Code to extract a consistent design system from your existing code:

Analyze all Tailwind classes used in the codebase. Extract:
1. All color values (including arbitrary ones) — propose a consolidated palette
2. All spacing values — standardize on Tailwind's default scale
3. All font sizes — create a typography scale
4. All border radius values — standardize
Create a tailwind.config.ts theme extension that replaces arbitrary values.

Claude Code generates:

// tailwind.config.ts
const config: Config = {
  content: ['./src/**/*.{js,ts,jsx,tsx,mdx}'],
  theme: {
    extend: {
      colors: {
        brand: {
          50: '#f0f9ff',
          100: '#e0f2fe',
          200: '#bae6fd',
          300: '#7dd3fc',
          400: '#38bdf8',
          500: '#0ea5e9',  // Primary
          600: '#0284c7',
          700: '#0369a1',
          800: '#075985',
          900: '#0c4a6e',
          950: '#082f49',
        },
        surface: {
          DEFAULT: '#ffffff',
          secondary: '#f8fafc',
          tertiary: '#f1f5f9',
          inverse: '#0f172a',
        },
      },
      spacing: {
        // Replace px-[17px] with px-4.5
        '4.5': '1.125rem',
        '18': '4.5rem',
      },
      fontSize: {
        'display-lg': ['3.5rem', { lineHeight: '1.1', letterSpacing: '-0.02em' }],
        'display': ['2.5rem', { lineHeight: '1.2', letterSpacing: '-0.01em' }],
        'heading': ['1.5rem', { lineHeight: '1.3' }],
        'subheading': ['1.125rem', { lineHeight: '1.4' }],
      },
      borderRadius: {
        'card': '0.75rem',
        'button': '0.5rem',
        'input': '0.375rem',
      },
    },
  },
};

Step 3: Extract repeated patterns into components

Ask Claude Code to find duplicated class patterns:

Find class strings that appear in 3 or more components with identical
or near-identical Tailwind classes. Extract them into reusable components
or @apply utilities.

Before (duplicated):

// Used in 8 different files
<button className="inline-flex items-center justify-center rounded-md bg-blue-600 px-4 py-2 text-sm font-medium text-white shadow-sm hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed">
  Submit
</button>

After (component):

// src/components/ui/Button.tsx
import { forwardRef, ButtonHTMLAttributes } from 'react';
import { cn } from '@/lib/utils';

const variants = {
  primary: 'bg-brand-500 text-white hover:bg-brand-600 focus:ring-brand-500',
  secondary: 'bg-surface-tertiary text-gray-900 hover:bg-gray-200 focus:ring-gray-500',
  danger: 'bg-red-600 text-white hover:bg-red-700 focus:ring-red-500',
  ghost: 'bg-transparent text-gray-700 hover:bg-surface-tertiary focus:ring-gray-500',
} as const;

const sizes = {
  sm: 'px-3 py-1.5 text-xs',
  md: 'px-4 py-2 text-sm',
  lg: 'px-6 py-3 text-base',
} as const;

interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
  variant?: keyof typeof variants;
  size?: keyof typeof sizes;
}

export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
  ({ className, variant = 'primary', size = 'md', ...props }, ref) => {
    return (
      <button
        ref={ref}
        className={cn(
          'inline-flex items-center justify-center rounded-button font-medium shadow-sm',
          'focus:outline-none focus:ring-2 focus:ring-offset-2',
          'disabled:opacity-50 disabled:cursor-not-allowed',
          'transition-colors duration-150',
          variants[variant],
          sizes[size],
          className,
        )}
        {...props}
      />
    );
  }
);

Step 4: Set up the cn() utility

The cn() function merges Tailwind classes without conflicts:

npm install clsx tailwind-merge
// src/lib/utils.ts
import { clsx, type ClassValue } from 'clsx';
import { twMerge } from 'tailwind-merge';

export function cn(...inputs: ClassValue[]): string {
  return twMerge(clsx(inputs));
}

This handles class conflicts correctly:

cn('px-4 py-2', 'px-6')
// Output: 'py-2 px-6' (px-4 is removed, not duplicated)

cn('text-red-500', condition && 'text-blue-500')
// Output: 'text-blue-500' when condition is true

Step 5: Organize long class strings

Ask Claude Code to refactor unreadable class strings:

Find all elements with more than 10 Tailwind classes. Refactor them
by either:
1. Extracting to a component (if pattern is reused)
2. Using cn() with named groups (if pattern is unique)
3. Moving to @apply in a CSS module (last resort)

Before:

<div className="relative flex min-h-screen flex-col items-center justify-center overflow-hidden bg-gradient-to-b from-slate-50 to-slate-100 px-4 py-12 sm:px-6 lg:px-8">

After:

const pageContainer = cn(
  'relative flex min-h-screen flex-col items-center justify-center',
  'overflow-hidden bg-gradient-to-b from-slate-50 to-slate-100',
  'px-4 py-12 sm:px-6 lg:px-8',
);

<div className={pageContainer}>

Step 6: Enable the Tailwind CSS IntelliSense plugin

Add the Tailwind CSS IntelliSense VS Code extension configuration:

{
  "tailwindCSS.experimental.classRegex": [
    ["cn\\(([^)]*)\\)", "'([^']*)'"],
    ["cva\\(([^)]*)\\)", "[\"'`]([^\"'`]*).*?[\"'`]"]
  ]
}

Step 7: Measure and verify

# Check production CSS size
npx tailwindcss -o /tmp/output.css --minify
ls -la /tmp/output.css

# A well-optimized Tailwind project produces 10-30KB gzipped
gzip -c /tmp/output.css | wc -c

Prevention

Add Tailwind rules to your CLAUDE.md:

## Tailwind CSS Rules
- Use design tokens from tailwind.config.ts, no arbitrary values
- Use the cn() utility for conditional classes
- Extract repeated patterns (3+ uses) into components
- Keep class strings under 10 utilities per element
- Use responsive prefixes consistently: sm → md → lg → xl
- Brand colors: brand-500 (primary), brand-700 (hover), brand-100 (bg)

**Written by Michael** — solo dev, Da Nang, Vietnam. 50K+ Chrome extension users. $500K+ on Upwork (100% Job Success). Runs 5 Claude Max subs in parallel. Built this site with autonomous agent fleets. [See what I'm building →](https://zovo.one)

I'm a solo developer in Vietnam. 50K Chrome extension users. $500K+ on Upwork. 5 Claude Max subscriptions running agent fleets in parallel. These are my actual CLAUDE.md templates, orchestration configs, and prompts. Not a course. Not theory. The files I copy into every project before I write a line of code. **[See what's inside →](https://zovo.one/lifetime?utm_source=ccg&utm_medium=cta-default&utm_campaign=claude-code-tailwind-css-optimization-guide)** $99 once. Free forever. 47/500 founding spots left.