To set color in Tailwind CSS, define your palette inside the theme.extend.colors object within your tailwind.config.js file. This approach overrides or extends default colors, allowing you to use utility classes like bg-indigo-500 or text-slate-900 consistently across your project.
Why Custom Color Tokens Matter
Default Tailwind colors are excellent starting points, but they rarely match specific brand identities perfectly. When you rely solely on the built-in palette, you often end up mixing slightly different shades of blue or gray because the defaults don’t align with your design system’s exact hex values. Custom tokens solve this by creating a single source of truth. Instead of hardcoding hex codes in every component, you reference semantic names like primary or secondary. This ensures that if you tweak the base hue, every button, border, and background updates automatically.
The goal is consistency. A custom token system prevents "color drift," where minor differences in rendering or manual entry cause visual inconsistencies. By defining these values centrally, you ensure that your brand’s primary indigo or secondary slate looks identical on every screen and component.
Generating a Harmonized Palette
Starting with a single brand color, such as #4F46E5, you need a scale of shades that work together. Manually adjusting lightness and saturation in hex codes often leads to muddy results or hue shifts. A more reliable method is using a tool that works in a perceptual color space like Oklch. This ensures that when you lighten a color, it becomes brighter without turning washed-out yellow, and when you darken it, it becomes richer without turning brownish.
For our worked example, we start with the brand color #4F46E5. We need a scale from light backgrounds to dark text colors. Using ColorWell, you can drop this hex value in to generate a harmonized indigo scale. The tool creates analogous and monochromatic variations that maintain the hue integrity. For instance, a light background might be #EEF2FF, while the primary button color remains #4F46E5, and the dark text hover state becomes #3730A3. These values are derived mathematically to ensure they look balanced together, rather than guessed randomly.
Verifying Accessibility with ColorWell
Choosing colors that look good is only half the battle; they must also be readable. WCAG accessibility standards require specific contrast ratios between text and background colors. For normal text, the ratio must be at least 4.5:1 (AA standard). For large text, it can be 3:1. If you pick colors by eye, you might miss these thresholds.
Continuing our example with the indigo scale, we check the contrast between our primary color #4F46E5 and white text. Many designers assume indigo is dark enough, but sometimes mid-tone blues fail AA compliance against white backgrounds. Using ColorWell’s instant WCAG checker, you verify each pair. The tool provides a clear AA or AAA verdict for text, large text, and UI components. If #4F46E5 on white yields a ratio of 4.5 or higher, it passes. If it fails, the tool suggests a slightly darker shade, such as #3730A3, which maintains the hue but increases contrast. This step ensures your design is inclusive without requiring manual calculation of luminance formulas.
Exporting to Tailwind Config
Once your palette is generated and verified, you need to translate these hex values into a format Tailwind understands. Tailwind uses a JavaScript configuration file to map utility classes to color values. Writing this by hand is tedious and error-prone. Instead, you can generate the exact code block needed.
For our indigo example, the exported configuration looks like this:
/** @type {import('tailwindcss').Config} */
module.exports = {
theme: {
extend: {
colors: {
indigo: {
50: '#EEF2FF',
100: '#E0E7FF',
200: '#C7D2FE',
300: '#A5B4FC',
400: '#818CF8',
500: '#4F46E5',
600: '#4338CA',
700: '#3730A3',
800: '#312E81',
900: '#1E1B4B',
},
},
},
},
plugins: [],
}
Notice the structure: the colors object is nested inside theme.extend. This ensures your custom indigo shades merge with Tailwind’s defaults rather than replacing them entirely. The keys (50, 100, etc.) correspond to the intensity levels, allowing you to use classes like bg-indigo-500 or text-indigo-700.
Implementing Tokens in Your Project
With the configuration block ready, you paste it into your project’s tailwind.config.js file. If you are using Tailwind v3+, this file is usually located at the root of your project. If you don’t have one, you can create it by running npx tailwindcss init -p in your terminal.
After saving the file, restart your development server if necessary. Tailwind scans your HTML or JSX files for classes and generates CSS on the fly. Because we extended the theme, existing utilities like bg-blue-500 still work, but now bg-indigo-500 uses our custom #4F46E5 value. You can test this by adding a simple div to your page:
<div class="bg-indigo-50 text-indigo-900 p-4">
<p class="font-bold text-indigo-700">Accessible Indigo Text</p>
</div>
The background will render as the light #EEF2FF, and the text will use the darker, high-contrast shades. This immediate feedback confirms that your tokens are wired correctly. If the colors look off, double-check that the hex values in your config match the exported ones exactly.
Best Practices for Color Naming
Naming conventions are as important as the colors themselves. Avoid names like blue-light or gray-dark. Instead, use numeric scales or semantic roles. Numeric scales (50, 100, 500, 900) are intuitive because higher numbers generally mean darker colors. This matches Tailwind’s default behavior and helps developers predict how a class will look without checking the CSS.
Semantic naming is another option, especially for complex design systems. You might define primary, secondary, and accent instead of specific hues. However, combining both approaches is often best. For example, you might map primary to your brand indigo and secondary to a neutral slate. This abstraction allows you to change the underlying hex values without rewriting every component’s class names.
Here is a comparison of naming strategies:
| Strategy | Example Class | Benefit | Drawback |
|---|---|---|---|
| Numeric Scale | bg-indigo-500 | Predictable hierarchy | Less semantic meaning |
| Semantic Role | bg-primary | Clear intent | Requires mapping layer |
| Hybrid | bg-primary-500 | Combines clarity and scale | More complex setup |
For most projects, sticking to numeric scales within named hues (like our indigo example) offers the best balance of readability and flexibility. It keeps your stylesheet clean and makes it easy for new team members to understand the visual hierarchy at a glance.