Intermediate15 min1 prerequisite

Customize Tailwind CSS configuration to match your design system and extend with custom utilities.

Customization & Configuration

Every project has unique design needs. Learn to customize Tailwind's configuration and extend it with your own utilities.

Configuration File

Basic Structure

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

const config: Config = {
  content: [
    './pages/**/*.{js,ts,jsx,tsx,mdx}',
    './components/**/*.{js,ts,jsx,tsx,mdx}',
    './app/**/*.{js,ts,jsx,tsx,mdx}',
  ],
  theme: {
    extend: {
      // Your customizations
    },
  },
  plugins: [],
}

export default config

Content Configuration

Tell Tailwind where to find class usage:

Terminal
content: [
  './app/**/*.{js,ts,jsx,tsx}',
  './components/**/*.{js,ts,jsx,tsx}',
  './lib/**/*.{js,ts}',
  // Include packages that use Tailwind
  './node_modules/@acme/ui/**/*.js',
]

Theme Customization

Extending vs Overriding

Extend (recommended): Adds to existing values

Terminal
theme: {
  extend: {
    colors: {
      brand: '#FF6B00', // Adds brand color
    },
  },
}

Override: Replaces all existing values

Terminal
theme: {
  colors: {
    brand: '#FF6B00', // Only this color exists now!
  },
}

Custom Colors

Terminal
theme: {
  extend: {
    colors: {
      // Single color
      brand: '#FF6B00',

      // Color with shades
      brand: {
        50: '#fff7ed',
        100: '#ffedd5',
        200: '#fed7aa',
        300: '#fdba74',
        400: '#fb923c',
        500: '#f97316',
        600: '#ea580c',
        700: '#c2410c',
        800: '#9a3412',
        900: '#7c2d12',
        950: '#431407',
      },

      // CSS variables (for themes)
      primary: 'hsl(var(--primary))',
      secondary: 'hsl(var(--secondary))',
      background: 'hsl(var(--background))',
      foreground: 'hsl(var(--foreground))',
    },
  },
}

Usage:

Terminal
<div className="bg-brand-500 text-brand-50">
  Brand colored element
</div>

Custom Fonts

Terminal
theme: {
  extend: {
    fontFamily: {
      sans: ['Inter', 'system-ui', 'sans-serif'],
      heading: ['Cal Sans', 'sans-serif'],
      mono: ['JetBrains Mono', 'monospace'],
    },
  },
}

Usage:

Terminal
<h1 className="font-heading text-4xl">
  Styled Heading
</h1>

Custom Spacing

Terminal
theme: {
  extend: {
    spacing: {
      '128': '32rem',
      '144': '36rem',
    },
  },
}

Custom Border Radius

Terminal
theme: {
  extend: {
    borderRadius: {
      '4xl': '2rem',
      '5xl': '2.5rem',
    },
  },
}

Custom Shadows

Terminal
theme: {
  extend: {
    boxShadow: {
      'soft': '0 2px 15px -3px rgba(0, 0, 0, 0.07)',
      'glow': '0 0 15px rgba(59, 130, 246, 0.5)',
    },
  },
}

Custom Animations

Terminal
theme: {
  extend: {
    animation: {
      'fade-in': 'fadeIn 0.5s ease-out',
      'slide-up': 'slideUp 0.3s ease-out',
      'spin-slow': 'spin 3s linear infinite',
    },
    keyframes: {
      fadeIn: {
        '0%': { opacity: '0' },
        '100%': { opacity: '1' },
      },
      slideUp: {
        '0%': { transform: 'translateY(10px)', opacity: '0' },
        '100%': { transform: 'translateY(0)', opacity: '1' },
      },
    },
  },
}

Usage:

Terminal
<div className="animate-fade-in">
  Animated content
</div>

CSS Variables Integration

Setting Up Variables

Terminal
/* globals.css */
@tailwind base;
@tailwind components;
@tailwind utilities;

@layer base {
  :root {
    --background: 0 0% 100%;
    --foreground: 222.2 84% 4.9%;
    --primary: 222.2 47.4% 11.2%;
    --primary-foreground: 210 40% 98%;
    --secondary: 210 40% 96.1%;
    --secondary-foreground: 222.2 47.4% 11.2%;
    --accent: 210 40% 96.1%;
    --accent-foreground: 222.2 47.4% 11.2%;
    --destructive: 0 84.2% 60.2%;
    --destructive-foreground: 210 40% 98%;
    --border: 214.3 31.8% 91.4%;
    --ring: 222.2 84% 4.9%;
    --radius: 0.5rem;
  }

  .dark {
    --background: 222.2 84% 4.9%;
    --foreground: 210 40% 98%;
    --primary: 210 40% 98%;
    --primary-foreground: 222.2 47.4% 11.2%;
    --secondary: 217.2 32.6% 17.5%;
    --secondary-foreground: 210 40% 98%;
    --accent: 217.2 32.6% 17.5%;
    --accent-foreground: 210 40% 98%;
    --destructive: 0 62.8% 30.6%;
    --destructive-foreground: 210 40% 98%;
    --border: 217.2 32.6% 17.5%;
    --ring: 212.7 26.8% 83.9%;
  }
}

Using Variables in Config

Terminal
theme: {
  extend: {
    colors: {
      border: 'hsl(var(--border))',
      background: 'hsl(var(--background))',
      foreground: 'hsl(var(--foreground))',
      primary: {
        DEFAULT: 'hsl(var(--primary))',
        foreground: 'hsl(var(--primary-foreground))',
      },
      secondary: {
        DEFAULT: 'hsl(var(--secondary))',
        foreground: 'hsl(var(--secondary-foreground))',
      },
      destructive: {
        DEFAULT: 'hsl(var(--destructive))',
        foreground: 'hsl(var(--destructive-foreground))',
      },
    },
    borderRadius: {
      lg: 'var(--radius)',
      md: 'calc(var(--radius) - 2px)',
      sm: 'calc(var(--radius) - 4px)',
    },
  },
}

Custom Utilities with @layer

Creating Custom Classes

Terminal
/* globals.css */
@layer utilities {
  .text-balance {
    text-wrap: balance;
  }

  .content-visibility-auto {
    content-visibility: auto;
  }

  .scrollbar-hide {
    -ms-overflow-style: none;
    scrollbar-width: none;
  }

  .scrollbar-hide::-webkit-scrollbar {
    display: none;
  }
}

Custom Components

Terminal
@layer components {
  .btn {
    @apply px-4 py-2 rounded-lg font-medium transition-colors;
  }

  .btn-primary {
    @apply btn bg-primary text-primary-foreground hover:bg-primary/90;
  }

  .btn-secondary {
    @apply btn bg-secondary text-secondary-foreground hover:bg-secondary/80;
  }

  .card {
    @apply bg-white dark:bg-gray-800 rounded-lg shadow-sm p-6;
  }

  .input {
    @apply w-full px-3 py-2 border border-gray-300 dark:border-gray-600
           rounded-lg bg-white dark:bg-gray-800
           focus:outline-none focus:ring-2 focus:ring-primary;
  }
}

Plugins

Official Plugins

Terminal
npm install @tailwindcss/typography @tailwindcss/forms @tailwindcss/aspect-ratio
Terminal
// tailwind.config.ts
plugins: [
  require('@tailwindcss/typography'),
  require('@tailwindcss/forms'),
  require('@tailwindcss/aspect-ratio'),
]

Typography Plugin

Styles prose content:

Terminal
<article className="prose prose-lg dark:prose-invert mx-auto">
  <h1>Article Title</h1>
  <p>Beautiful typography for long-form content...</p>
  <ul>
    <li>Styled lists</li>
    <li>And more</li>
  </ul>
</article>

Forms Plugin

Resets form elements:

Terminal
<input type="text" className="form-input" />
<select className="form-select" />
<textarea className="form-textarea" />
<input type="checkbox" className="form-checkbox" />

Custom Plugin

Terminal
const plugin = require('tailwindcss/plugin')

plugins: [
  plugin(function({ addUtilities, addComponents, theme }) {
    // Add utilities
    addUtilities({
      '.drag-none': {
        '-webkit-user-drag': 'none',
        'user-drag': 'none',
      },
    })

    // Add components
    addComponents({
      '.card': {
        backgroundColor: theme('colors.white'),
        borderRadius: theme('borderRadius.lg'),
        padding: theme('spacing.6'),
        boxShadow: theme('boxShadow.md'),
      },
    })
  }),
]

Safelist

Force include classes that aren't in source files:

Terminal
safelist: [
  'bg-red-500',
  'text-3xl',
  'lg:text-4xl',
  // Patterns
  {
    pattern: /bg-(red|green|blue)-(100|200|300)/,
  },
]

Useful for dynamic classes:

Terminal
// Without safelist, this might not work
const color = 'red'
<div className={`bg-${color}-500`}>

Common Configurations

shadcn/ui Config

Terminal
const config: Config = {
  darkMode: ['class'],
  content: ['./components/**/*.{ts,tsx}', './app/**/*.{ts,tsx}'],
  theme: {
    container: {
      center: true,
      padding: '2rem',
      screens: {
        '2xl': '1400px',
      },
    },
    extend: {
      colors: {
        border: 'hsl(var(--border))',
        input: 'hsl(var(--input))',
        ring: 'hsl(var(--ring))',
        background: 'hsl(var(--background))',
        foreground: 'hsl(var(--foreground))',
        primary: {
          DEFAULT: 'hsl(var(--primary))',
          foreground: 'hsl(var(--primary-foreground))',
        },
        // ... more colors
      },
      borderRadius: {
        lg: 'var(--radius)',
        md: 'calc(var(--radius) - 2px)',
        sm: 'calc(var(--radius) - 4px)',
      },
    },
  },
  plugins: [require('tailwindcss-animate')],
}

AI Tool Standard Config

Most AI tools generate configs like:

Terminal
const config: Config = {
  content: [
    './pages/**/*.{js,ts,jsx,tsx,mdx}',
    './components/**/*.{js,ts,jsx,tsx,mdx}',
    './app/**/*.{js,ts,jsx,tsx,mdx}',
  ],
  darkMode: 'class',
  theme: {
    extend: {
      fontFamily: {
        sans: ['var(--font-inter)', 'system-ui', 'sans-serif'],
      },
    },
  },
  plugins: [],
}

Debugging Tips

Class Not Working?

  1. Check content array includes the file
  2. Run build and check output CSS
  3. Look for typos in class names
  4. Use Tailwind IntelliSense extension

Find Classes in Output

Terminal
# See generated CSS
npx tailwindcss -i input.css -o output.css --content './src/**/*.tsx'

Check Configuration

Terminal
# Print resolved config
npx tailwindcss --help

Summary

  • Extend theme instead of override to keep defaults
  • CSS variables enable runtime theming
  • @layer for custom utilities and components
  • Plugins add features like typography and forms
  • Content array must include all files using Tailwind

Module Complete

You've learned Tailwind CSS essentials:

  1. ✅ Introduction and utility classes
  2. ✅ Responsive design and dark mode
  3. ✅ Customization and configuration

Continue with shadcn/ui to learn the component library built on Tailwind.

Mark this lesson as complete to track your progress