Extending the Theme
Customize tailwind.config.js with theme.extend to add your own brand colors, fonts, and spacing values without losing Tailwind's defaults.
Introduction
Every project eventually needs a color or a font size that is not in Tailwind's default palette. Rather than hard-coding one-off values with arbitrary syntax like bg-[#0f5cff] everywhere, you can teach Tailwind about your design system once, in tailwind.config.js, and then use it through ordinary utility classes like any built-in value.
- The difference between theme and theme.extend, and why it matters.
- How to register custom brand colors, fonts, and spacing values.
- How those custom tokens become new utility classes automatically.
theme vs theme.extend
tailwind.config.js has a top-level theme object. Anything you put directly under theme replaces Tailwind's built-in values for that key entirely. Anything you put under theme.extend is merged on top of the defaults instead — you keep every default color, font, and spacing value, and simply add new ones alongside them.
// tailwind.config.jsmodule.exports = { theme: { // ⚠️ Replaces ALL default colors — bg-red-500 etc. stop existing colors: { brand: '#0f5cff', }, extend: { // ✅ Adds to the defaults — bg-red-500 still works, plus bg-brand colors: { brand: '#0f5cff', }, }, },};Defining colors directly under theme (not theme.extend) silently deletes Tailwind's entire default color palette. Unless you are intentionally building a fully custom design system from scratch, always add new values under theme.extend.
Adding Brand Colors
Colors are usually defined as a shade scale (50 through 900) so you get the same light-to-dark flexibility Tailwind's built-in colors offer.
// tailwind.config.jsmodule.exports = { content: ['./app/**/*.{js,ts,jsx,tsx}', './components/**/*.{js,ts,jsx,tsx}'], theme: { extend: { colors: { brand: { 50: '#eef4ff', 100: '#d9e6ff', 500: '#3366ff', 600: '#2451e0', 700: '#1a3fb8', 900: '#132a7a', }, }, }, }, plugins: [],};<button class="bg-brand-500 hover:bg-brand-600 text-white px-4 py-2 rounded-md"> Get Started</button>Click Run to see what this code prints.
Adding Custom Fonts
Font families work the same way. Extend theme.fontFamily with a name and a stack of font names, usually after loading the font itself via next/font, a <link> tag, or an @font-face rule.
module.exports = { theme: { extend: { fontFamily: { display: ['Poppins', 'ui-sans-serif', 'system-ui'], }, }, },};<h1 class="font-display text-4xl font-bold">Learn Tailwind CSS</h1>Adding Custom Spacing
You are not limited to colors and fonts — almost every theme key (spacing, borderRadius, fontSize, boxShadow, and more) can be extended the same way. Here a custom spacing value fills a gap between Tailwind's built-in steps.
module.exports = { theme: { extend: { spacing: { 18: '4.5rem', // between 16 (4rem) and 20 (5rem) 128: '32rem', }, borderRadius: { xl: '1rem', }, }, },};<div class="p-18 rounded-xl bg-brand-50">Custom spacing and radius</div>Extending Breakpoints
Screens (breakpoints) can also be extended if your design needs a size Tailwind does not ship by default, such as an extra-wide desktop breakpoint.
module.exports = { theme: { extend: { screens: { '3xl': '1920px', }, }, },};<div class="grid grid-cols-2 3xl:grid-cols-6">...</div>Using Your Tokens
Once registered, custom tokens behave exactly like Tailwind's built-in ones: they work with every variant (hover:bg-brand-600, md:font-display, dark:bg-brand-900) and show up in editor autocomplete if you use the official Tailwind CSS IntelliSense extension.
Common Mistakes
- Defining colors or fonts under theme instead of theme.extend, wiping out Tailwind's defaults by accident.
- Forgetting to restart the dev server after editing tailwind.config.js in some setups where config changes are not hot-reloaded.
- Using inconsistent naming, like brandBlue in one place and brand-blue in another, making the scale confusing to use.
- Reaching for arbitrary values like bg-[#0f5cff] repeatedly instead of registering the color once in the config.
Best Practices
- Always extend rather than replace unless you are deliberately discarding Tailwind's defaults.
- Model custom colors as a 50–900 shade scale so they compose the same way built-in colors do.
- Keep design tokens centralized in tailwind.config.js instead of scattering hex codes through arbitrary-value utilities.
- Name tokens after their role in your design system (brand, accent, surface), not a literal color name that might become inaccurate later.
Frequently Asked Questions
Yes — under theme.extend.colors, set { blue: { 500: '#0055ff' } } and only that shade changes; the rest of the blue scale stays default.
theme.extend always wins for that key's merge; entries there are added on top of (and can override individual values within) the defaults rather than replacing the whole object.
Yes, once a token is registered in the theme it is a first-class utility and works with every variant Tailwind supports.
Key Takeaways
- theme replaces Tailwind's defaults for a key; theme.extend merges on top of them.
- Colors, fonts, spacing, radii, and breakpoints can all be extended the same way.
- Custom tokens become real utility classes that support every Tailwind variant.
- Centralizing values in the config avoids scattering one-off arbitrary values through your markup.
Summary
You learned how to extend Tailwind's theme with your own brand colors, fonts, spacing, and breakpoints, while keeping every default utility intact. Next, you will see how official Tailwind plugins add entirely new sets of utilities for things like form styling and rich text.