iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

tailwind.config

tailwind.config.js: content paths, theme.extend, plugins, and the choices that shape your design system.

Tailwind — config

EXAMPLE
// ===== The file =====
// tailwind.config.js (or .ts via type-stripping)
import typography from '@tailwindcss/typography';
import forms from '@tailwindcss/forms';
import { Config } from 'tailwindcss';

export default {
  // 1. Where to scan for classes
  content: [
    './index.html',
    './src/**/*.{js,ts,jsx,tsx,vue,svelte}',
  ],

  // 2. Dark mode strategy: 'media' (default), 'class', or ['class', '.dark']
  darkMode: 'class',

  theme: {
    // Replacing the default scale (rarely):
    screens: { sm: '640px', md: '768px', lg: '1024px', xl: '1280px' },
    // Extending (the common path):
    extend: {
      colors: {
        brand: { 50: '#eff6ff', 500: '#2563eb', 700: '#1d4ed8' },
      },
      fontFamily: {
        sans: ['Inter var', 'ui-sans-serif', 'system-ui'],
      },
      spacing: {
        18: '4.5rem',
        128: '32rem',
      },
      borderRadius: {
        '4xl': '2rem',
      },
      animation: {
        wiggle: 'wiggle 1s ease-in-out infinite',
      },
      keyframes: {
        wiggle: {
          '0%, 100%': { transform: 'rotate(-2deg)' },
          '50%': { transform: 'rotate(2deg)' },
        },
      },
    },
  },

  plugins: [typography, forms],
} satisfies Config;

// ===== Content paths matter =====
// The 'content' globs decide what classes are emitted.
// Miss a path -> classes 'silently' do nothing.
// Include node_modules of design systems if you consume their classes:
content: [
  './src/**/*.{ts,tsx}',
  './node_modules/@my-org/ui/**/*.js',
],

// ===== Safelist =====
// Force-include classes that won't be detected statically (e.g. dynamic names):
content: {
  files: ['./src/**/*.{ts,tsx}'],
  transform: {
    // optional per-extension transforms
  },
},
safelist: ['bg-red-500', { pattern: /bg-(red|green|blue)-(100|500|900)/ }],

// ===== Theme tokens drive consistency =====
// Once you extend the theme, classes follow:
// bg-brand-500, text-brand-700, font-sans, p-18 ...

// ===== Plugins =====
// Built-in features you toggle:
//   @tailwindcss/typography  -> prose-* for long content
//   @tailwindcss/forms       -> sane defaults for form controls
//   @tailwindcss/container-queries
//   @tailwindcss/aspect-ratio (built-in since 3.0)

// Custom plugin example:
import plugin from 'tailwindcss/plugin';
const myPlugin = plugin(function ({ addBase, addComponents, theme }) {
  addBase({ 'h1': { fontSize: theme('fontSize.2xl') } });
  addComponents({ '.card': { padding: theme('spacing.4'), borderRadius: theme('borderRadius.lg') } });
});

// ===== Important things to know =====
// - 'content' is NOT the same as 'purge' (which was a v2 concept)
// - JIT mode is default in 3+; no need to opt in
// - Arbitrary values text-[13px] are powerful — use sparingly
// - 'extend' beats 'replace'; replacing the scale resets everything

// ===== Patterns to internalise =====
// - Extend; rarely replace
// - Brand colours, fonts, spacing in config (one source of truth)
// - Plugins for cross-cutting helpers (prose, forms, container queries)
// - Restart the dev server after config changes

// ===== Pitfalls =====
// - content paths missing a folder -> classes do not appear
// - Replacing the colour palette with a small set -> losing utility coverage
// - Long arbitrary values in markup instead of token names
// - Mixing v2 and v3 patterns from different tutorials

Why it matters

tailwind.config.js is your design system. Extend the theme with brand tokens, register plugins for cross-cutting helpers, and watch the content paths like a hawk. The config file is small but load-bearing — every class your app emits passes through it.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
// tailwind.config.js
export default {
    content: ['./src/**/*.{html,js,jsx,ts,tsx}'],
    theme: { extend: { colors: { brand: '#04AA6D' } } },
    plugins: [],
};
Try it Yourself »

Discussion

Loading…