Tailwind CSS ships with a beautiful default palette, but the moment you need to match your brand color, you are on your own. Here is how to generate a full 50-to-950 shade scale from any hex color, understand the HSL math behind it, and get config-ready output you can paste directly into your project.
Every color in Tailwind has 11 shades, numbered from 50 (lightest) to 950 (darkest). Here is Tailwind’s blue palette as reference:
The key insight: this is not random. Each shade follows a deliberate lightness curve. The 500 shade is the "base" color. Shades below 500 get progressively lighter (higher HSL lightness, slightly lower saturation). Shades above 500 get progressively darker (lower lightness, adjusted saturation to avoid muddiness). Understanding this curve is how you generate palettes that feel as polished as Tailwind’s built-in ones.
Pick the hex value of your brand’s primary color. This will become your 500 shade — the mid-tone anchor of the entire scale. For example, #8b5cf6 (Tailwind’s violet-500). If you only have an RGB value, convert it to hex first.
HSL (Hue, Saturation, Lightness) is the color model that makes palette generation intuitive. #8b5cf6 converts to hsl(263, 90%, 66%). The hue (263) stays constant across all shades. The saturation and lightness change to create tints and shades.
This is the core technique. For Tailwind-compatible palettes, the lightness values typically follow this progression:
| Shade | Lightness Range | Use Case |
|---|---|---|
| 50 | 95-97% | Page backgrounds, subtle fills |
| 100 | 90-93% | Hover backgrounds, secondary fills |
| 200 | 82-87% | Borders on light backgrounds |
| 300 | 72-78% | Disabled states, placeholder text |
| 400 | 62-68% | Icons, secondary buttons |
| 500 | 50-60% | Primary buttons, links, brand color |
| 600 | 42-48% | Hover states for primary elements |
| 700 | 34-40% | Active states, dark accents |
| 800 | 26-32% | Headings on light backgrounds |
| 900 | 18-24% | Body text on light backgrounds |
| 950 | 8-14% | Near-black, dark mode backgrounds |
Pure lightness shifts produce muddy darks and washed-out lights. The fix: slightly decrease saturation for very light shades (50-200) and slightly increase or maintain saturation for dark shades (700-950). This prevents the "dirty grey" look in dark shades and the "neon pastel" look in light shades.
Use the Pure-Flon Color Palette Generator to do steps 2-4 automatically. Enter your hex color, get a full 11-shade palette with the correct lightness curve. Copy the output directly into your tailwind.config.js.
Once you have your palette, add it to your Tailwind config. You can either extend the default colors (keep blue, red, etc.) or replace them entirely:
After adding this, you can use classes like bg-brand-500, text-brand-900, border-brand-200, and hover:bg-brand-600 throughout your templates. The naming convention is {property}-{color}-{shade}.
Hue is the "color" itself, expressed as a degree on the color wheel. Red is 0, yellow is 60, green is 120, cyan is 180, blue is 240, magenta is 300. For a single-color palette, the hue stays constant across all shades. You might shift it by 2-5 degrees in extreme light or dark shades to add warmth (toward yellow) or coolness (toward blue), but this is optional refinement.
Saturation controls how vivid the color is. 100% is fully saturated, 0% is pure grey. For Tailwind palettes, the mid-range shades (400-600) tend to have the highest saturation. Light shades (50-200) should have slightly lower saturation to avoid looking like highlighter ink. Dark shades (800-950) can maintain or slightly reduce saturation to stay rich without looking muddy.
Lightness is the primary lever for generating shade scales. 0% is black, 100% is white, and 50% is the "pure" color. Tailwind’s 500 shade typically sits around 50-60% lightness. The key to good palettes is non-linear spacing: the steps between 50 and 200 are larger (5-7% each), while steps between 700 and 950 are smaller (4-6% each). This produces perceptually even spacing because human vision is more sensitive to lightness differences in dark ranges.
Dividing 0-100% into 11 equal steps (9.1% each) produces a palette that looks wrong. The light end is too dense (three nearly-identical pastels) and the dark end has jarring jumps. Good palettes use a curve, not a line. More spacing at the light end, tighter spacing at the dark end.
Keeping saturation at, say, 90% for every shade from 50 to 950 makes the light shades look like neon candy and the dark shades look muddy or brownish. Reduce saturation by 15-30% for the 50 and 100 shades. The dark shades (800-950) can maintain saturation or reduce slightly to stay clean.
WCAG accessibility requires a 4.5:1 contrast ratio for normal text and 3:1 for large text. When using your palette shades, verify that text colors against background colors meet these ratios. Typically, use shades 700-950 for text on light backgrounds and 50-300 for text on dark backgrounds. The 400-500 range often fails contrast checks against both white and black backgrounds.
Some tools generate palettes by linearly interpolating between two hex values (e.g., white to your brand color to black). This produces uneven perceptual steps because hex/RGB space is not perceptually uniform. HSL-based generation with manual curve tuning produces significantly better results. Even better: use OKLCH or CIELAB for perceptually uniform spacing, though HSL is good enough for most projects.
Tailwind CSS v4 moves color configuration from JavaScript to CSS using the new @theme directive. Instead of editing tailwind.config.js, you define colors directly in your CSS:
The utility classes work the same way: bg-brand-500, text-brand-200, etc. The output from our color palette generator works with both v3 (config.js) and v4 (CSS variables) — just copy the hex values into whichever format your project uses.
Tailwind uses a numeric scale from 50 to 950: 50 is the lightest tint (nearly white), 500 is the base mid-tone, and 950 is the darkest shade (nearly black). Each step represents a perceptual lightness increment. The default palette has 11 shades per color (50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950). When generating custom palettes, maintaining consistent perceptual spacing between these steps is what makes the palette feel cohesive.
Tailwind supports both, but HSL has a significant advantage for custom palettes: you can generate an entire shade range by adjusting only the lightness value while keeping hue and saturation constant. This produces perceptually uniform progressions. In your tailwind.config.js, you can use either format. If you want to support Tailwind’s opacity modifier (e.g., bg-blue-500/50), use the HSL channel syntax and define CSS variables without the hsl() wrapper.
Yes, and this is the most common use case. Start with your brand hex color, convert it to HSL, and use that as your 500 (mid-tone) shade. Then generate lighter shades (50-400) by increasing lightness and slightly decreasing saturation, and darker shades (600-950) by decreasing lightness and slightly adjusting saturation. The Pure-Flon Color Palette Generator does this automatically — enter your brand color and get a full 50-950 scale ready to paste into your Tailwind config.
Like free tools with no ads? Support the project