Skip to content

Understanding the Tailwind CSS Color System: Shades, Custom Palettes and Accessibility

Tailwind CSS ships with one of the most thoughtfully designed color systems in any CSS framework. Instead of giving you a handful of named colors, it provides a full palette of 22 color families, each with 11 carefully tuned shades ranging from near-white to near-black. Understanding how this system works helps you build consistent, accessible interfaces without constantly reaching for custom hex values.

How Tailwind Organizes Colors

Every color in Tailwind follows a naming pattern: the color family followed by a numeric shade. For example, blue-500 is the base blue, while blue-100 is a very light tint and blue-900 is a deep dark shade.

The shade scale uses these stops: 50, 100, 200, 300, 400, 500, 600, 700, 800, 900 and 950. The 50 shade is the lightest (almost white with a hint of the color), and 950 is the darkest (nearly black with color undertones). This 11-stop scale gives you enough granularity for backgrounds, borders, text and interactive states without overwhelming you with choices.

The Default Palette

Tailwind includes 22 color families out of the box: slate, gray, zinc, neutral, stone (five grays with different undertones), red, orange, amber, yellow, lime, green, emerald, teal, cyan, sky, blue, indigo, violet, purple, fuchsia, pink and rose. Having multiple gray scales is one of Tailwind's standout features. Slate has a cool blue undertone, zinc is slightly warm, and neutral is perfectly balanced with no undertone at all.

For most projects, you will pick one gray family for surfaces and text, then one or two accent colors for interactive elements and branding. A common combination is zinc for grays with indigo as the primary accent.

Adding Custom Colors

When your brand colors do not match any default palette, you can extend or override the color configuration. In Tailwind v4, you configure custom colors directly in your CSS file using the @theme directive.

@theme {
--color-brand-50: #f0f5ff;
--color-brand-100: #e0ebff;
--color-brand-200: #b3cdff;
--color-brand-500: #3366ff;
--color-brand-700: #1a3dcc;
--color-brand-900: #0d1f66;
--color-brand-950: #061033;
}

This creates utility classes like bg-brand-500, text-brand-700 and so on. The key is to define all the shade stops you need so the palette works across backgrounds, text and borders.

Generating Balanced Shade Scales

Creating a good shade scale is harder than it looks. Simply darkening and lightening a base color in equal steps usually produces muddy mid-tones and washed-out light shades. Here are some principles for generating better scales.

  • Work in perceptual color spaces. Generating shades in OKLCH or OKLAB produces more visually uniform steps than working in hex or RGB directly. The perceived lightness between each shade should feel even.
  • Adjust saturation along with lightness. Very light shades (50, 100) look better with reduced saturation, while mid-tones (400, 500, 600) can carry the most saturation. Very dark shades often need slightly increased saturation to avoid looking flat.
  • Maintain hue consistency. Some color spaces cause hue shift as you adjust lightness. A blue that drifts toward purple in dark shades looks inconsistent. Check hue values across the entire scale.
  • Use tools to automate the process. Palette generators that understand perceptual uniformity can save hours of manual tweaking and produce results that rival Tailwind's built-in scales.

Color Accessibility and Contrast

Color is not just about aesthetics. WCAG (Web Content Accessibility Guidelines) requires specific contrast ratios between text and its background to ensure readability. For normal-sized text, the minimum ratio is 4.5:1 (AA level). For large text (18px bold or 24px normal), it is 3:1.

Here are some practical rules of thumb when using Tailwind colors.

  • On a white background, use shades 600 or darker for body text to meet AA contrast requirements.
  • On dark backgrounds (900, 950), use shades 300 or lighter for text.
  • Colored text on colored backgrounds is tricky. Always verify the contrast ratio rather than relying on visual judgment, especially for users with color vision deficiencies.
  • Do not rely on color alone to communicate state. Pair color changes with icons, underlines or labels so the information is conveyed through multiple channels.

Dark Mode Considerations

Tailwind makes dark mode straightforward with the dark: variant, but color choices need careful thought. A common mistake is simply inverting the shade numbers (using 100 in light mode and 900 in dark mode). This often produces poor contrast or overly bright surfaces.

Better approaches include keeping background surfaces in the 900 to 950 range for dark mode and using 100 to 200 for text. For accent colors, the 400 shade often works well on dark backgrounds while 600 works better on light backgrounds. Test both modes at every stage of development rather than treating dark mode as an afterthought.

<button class="
bg-indigo-600 text-white
dark:bg-indigo-500 dark:text-indigo-50
">
Save Changes
</button>

Semantic Color Naming

As projects grow, scattering raw color utilities like text-blue-600 across hundreds of components makes global color changes painful. Semantic naming creates a layer of abstraction between your design intent and the actual color values.

@theme {
--color-primary: var(--color-indigo-600);
--color-secondary: var(--color-zinc-600);
--color-danger: var(--color-red-600);
--color-success: var(--color-emerald-600);
}

Now you write bg-primary instead of bg-indigo-600. When the brand color changes from indigo to blue, you update one line instead of hundreds. This pattern also makes theming and white-labeling much simpler.

Practical Tips

  • Limit your active palette. Even though Tailwind ships 22 color families, most interfaces look best with 1 to 3 colors plus a gray scale. Constraint breeds consistency.
  • Use opacity modifiers for subtle variations. Instead of picking a new shade, try bg-indigo-500/10 for a light tinted background. This keeps you within the same color family and adapts automatically to different base backgrounds.
  • Document your color decisions. A simple table mapping color roles (primary, surface, border, muted text) to specific Tailwind classes ensures the entire team uses colors consistently.
  • Test with grayscale. Temporarily desaturate your UI to verify that hierarchy and structure are clear without relying on color differences. If the layout falls apart in grayscale, you are over-relying on color.

Try it yourself

Generate a complete Tailwind-compatible color palette from any base color. Preview all 11 shades, check contrast ratios and copy the configuration code.

Open Tailwind Color Palette Generator →