Tailwind Configuration & Theming
p-4 into 1rem of padding or text-blue-600 into a specific shade of blue, and it is fully customizable per project. Understanding how to configure it is the difference between a Tailwind site that looks like every other Tailwind site and one with its own visual identity.tailwind.config.js
theme key, and everything inside theme.extend is merged on top of Tailwind's default design tokens rather than replacing them:/** @type {import('tailwindcss').Config} */
module.exports = {
content: ['./src/**/*.{html,js,jsx,ts,tsx}'],
theme: {
extend: {
colors: {
brand: {
50: '#eef6ff',
100: '#d9eaff',
500: '#2f7ff0',
600: '#1c63d1',
900: '#122a52',
},
},
spacing: {
18: '4.5rem',
112: '28rem',
},
fontFamily: {
display: ['Sora', 'ui-sans-serif', 'system-ui'],
},
screens: {
xs: '480px',
},
},
},
plugins: [],
}bg-brand-500, p-18, font-display, and the new xs: breakpoint prefix all become valid utility classes, alongside every default Tailwind utility that was already there.extend vs. overriding the default theme
theme.extend as additive, but a key placed directly under theme (outside extend) completely replaces that entire token category:Placement | Effect | When to use it |
|---|---|---|
| Adds new colors alongside the full default palette ( | Almost always — you rarely want to lose the default palette entirely |
| Replaces the ENTIRE default color palette with only what you list | Design systems that want a small, closed, fully custom palette (no stray |
| Adds new spacing values on top of the default 4px-based scale | Adding a few one-off sizes |
| Replaces the entire spacing scale | Rare — usually only for a from-scratch design system with its own scale |
theme instead of theme.extend, which silently deletes every built-in color. Classes like text-gray-500 or bg-red-500 that were working a moment ago will simply stop generating any CSS, with no error — the class just won't exist in the output. If utilities you expect suddenly don't apply, check whether the corresponding theme key was placed outside extend.A worked example: a custom brand palette
extend.colors under a semantic name, rather than a raw color name:theme: {
extend: {
colors: {
brand: {
50: '#f0f7ff',
100: '#dbeafe',
200: '#bfdbfe',
300: '#93c5fd',
400: '#60a5fa',
500: '#3b82f6', // the "base" brand color
600: '#2563eb',
700: '#1d4ed8',
800: '#1e40af',
900: '#1e3a8a',
},
},
},
},bg-brand-600, text-brand-50, and border-brand-300 are all available, and — crucially — if the brand color ever changes, updating it happens in exactly one place instead of hunting through every component for a hardcoded hex value.Custom utilities via plugins
addUtilities:const plugin = require('tailwindcss/plugin')
module.exports = {
// ...
plugins: [
plugin(({ addUtilities }) => {
addUtilities({
'.text-shadow-sm': {
textShadow: '0 1px 2px rgba(0, 0, 0, 0.2)',
},
'.scrollbar-hide': {
scrollbarWidth: 'none',
'&::-webkit-scrollbar': { display: 'none' },
},
})
}),
],
}For anything beyond a handful of utilities, reach for an official first-party plugin first —
@tailwindcss/forms,@tailwindcss/typography, and@tailwindcss/container-queriescover the most common needs.Plugins can also read from and extend the theme, so a plugin-provided utility can still respect your custom spacing or color scale.
Tailwind v4: CSS-first configuration
@theme block, instead of (or alongside) a JavaScript config file:@import "tailwindcss";
@theme {
--color-brand-500: #3b82f6;
--color-brand-600: #2563eb;
--spacing-18: 4.5rem;
--font-display: "Sora", sans-serif;
}color: var(--color-brand-600)), not just through generated utility classes — a nice side benefit of moving configuration into CSS rather than a separate JS object. If you're starting a new project, check which major version your toolchain targets before deciding whether to reach for tailwind.config.js or an @theme block, since the two approaches (and their exact capabilities) differ by version.w-[327px] everywhere. Arbitrary values are a useful escape hatch, but a config (or @theme block) that captures your real spacing/color/type scale keeps utility classes meaningful and consistent across the whole codebase.