Tool Guides

Tailwind Shade Generator: Custom Color Scales Made Easy

7 min read

Tailwind CSS ships with a carefully crafted color palette: 22 hues, each with 11 shades from 50 to 950. It covers the vast majority of use cases โ€” but the moment you need to use your brand's specific blue, or a purple that matches your company logo exactly, the built-in palette is not enough.

This is where a shade generator becomes essential. You provide one color โ€” your brand primary, an accent, a semantic color โ€” and the generator outputs a complete 50-to-950 scale, formatted exactly as a Tailwind CSS configuration object, ready to drop into your tailwind.config.js.

This guide explains how Tailwind's shade system works, how to generate custom scales using ColorFYI's Shade Generator, and how to configure Tailwind to use them effectively, including dark mode.


How Tailwind's Shade System Works

Tailwind's color scale is built around an 11-step numeric system:

50  100  200  300  400  500  600  700  800  900  950

Each step represents a perceptual lightness level:

  • 50 is the lightest โ€” nearly white, just a hint of color
  • 500 is the "pure" color โ€” fully saturated, mid-lightness
  • 950 is the darkest โ€” nearly black, deep tint

The numbers are not arbitrary. They are spaced to create roughly even perceptual jumps in lightness. The gap between 100 and 200 looks about the same to your eye as the gap between 700 and 800.

Why 11 steps?

11 steps provide enough granularity to cover every common use case in a UI:

Shade Primary Use
50 Page and section backgrounds, subtle tints
100 Hover backgrounds for ghost/outline elements
200 Disabled state backgrounds, subtle borders
300 Decorative borders, subtle dividers
400 Placeholder text, secondary icon color
500 The base color โ€” filled buttons, links
600 Hover state for filled interactive elements
700 Active/pressed state, accessible text on light backgrounds
800 Dark text on colored backgrounds, emphasis text
900 Headings, high-contrast text
950 Near-black tints, maximum contrast text

This system means every Tailwind color works like a mini design system on its own. If you need white text readable on a filled button, use -600. If you need a barely-there background tint, use -50.


The 50โ€“950 Scale in Detail

Let us look at a concrete example using Tailwind's built-in violet scale:

Shade Hex RGB Lightness (L in OKLCH)
violet-50 #F5F3FF ~98%
violet-100 #EDE9FE ~95%
violet-200 #DDD6FE ~89%
violet-300 #C4B5FD ~80%
violet-400 #A78BFA ~70%
violet-500 #8B5CF6 ~57%
violet-600 #7C3AED ~48%
violet-700 #6D28D9 ~40%
violet-800 #5B21B6 ~33%
violet-900 #4C1D95 ~26%
violet-950 #2E1065 ~15%

Notice that the base color violet-500 sits at roughly 57% lightness โ€” not exactly the middle of 0โ€“100%, but positioned slightly above the midpoint to keep the scale visually balanced. Very dark shades compress into a smaller lightness range (15โ€“40%) because the human eye distinguishes dark shades less precisely than light ones.


Generating Custom Color Scales

Using ColorFYI's Shade Generator

The Shade Generator takes any hex code and outputs a complete Tailwind-formatted scale. Here is the workflow:

Step 1: Enter your brand color in the input field.

For example, your brand uses the exact blue #0057B8 โ€” a medium-dark blue used by many enterprise brands.

Step 2: The generator computes all 11 shades using a perceptually uniform algorithm, showing you the hex code and a visual preview of each step.

Step 3: Copy the generated Tailwind configuration block.

The output for #0057B8 looks approximately like this:

brand: {
  50:  '#E6F0FF',
  100: '#CCE1FF',
  200: '#99C3FF',
  300: '#66A4FF',
  400: '#3386FF',
  500: '#0057B8',  // Your input color, anchored at 500
  600: '#0049A3',
  700: '#003B8A',
  800: '#002D6B',
  900: '#001F4D',
  950: '#001230',
},

What "anchoring" means

The shade generator anchors your input color at the 500 position by default. This means the input color becomes the center of the scale โ€” five lighter shades are generated above it, and five darker shades below.

Some generators allow you to anchor at a different position. If your brand color is already a very dark navy, anchoring it at 700 or 800 may produce a more useful range. If it is a very light pastel, anchoring at 200 or 300 makes more sense. The Shade Generator lets you adjust the anchor point.

Why perceptual uniformity matters

A naive shade generator might just decrease the HSL L value by equal increments: 95%, 85%, 75%, 65%, 55%, 45%, 35%, 25%, 15%. The math is simple, but the visual result is uneven. The transitions at the light end of the scale look spaced further apart than at the dark end, because human vision is more sensitive to lightness differences in midtones.

ColorFYI's generator uses OKLCH lightness interpolation, which produces steps that appear visually equidistant โ€” matching the perceptual quality of Tailwind's hand-crafted default scales.


Configuring tailwind.config.js

Extending with a custom color

The safest way to add a custom color scale is to extend Tailwind's defaults rather than replace them:

// tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
  theme: {
    extend: {
      colors: {
        brand: {
          50:  '#E6F0FF',
          100: '#CCE1FF',
          200: '#99C3FF',
          300: '#66A4FF',
          400: '#3386FF',
          500: '#0057B8',
          600: '#0049A3',
          700: '#003B8A',
          800: '#002D6B',
          900: '#001F4D',
          950: '#001230',
        },
      },
    },
  },
}

After adding this, you can use classes like bg-brand-500, text-brand-700, border-brand-200, and hover:bg-brand-600 throughout your project.

Replacing a built-in color

If you want to completely replace a default color (e.g., replace Tailwind's blue with your brand blue):

module.exports = {
  theme: {
    extend: {
      colors: {
        blue: {
          50:  '#E6F0FF',
          // ... through 950
        },
      },
    },
  },
}

Classes like bg-blue-500, text-blue-700 will now use your custom scale instead of Tailwind's built-in blue.

Using CSS variables for runtime theming

For applications that need runtime theme switching (e.g., white-label products, user-customizable themes), define the scale as CSS custom properties:

/* globals.css */
:root {
  --color-brand-50:  #E6F0FF;
  --color-brand-100: #CCE1FF;
  --color-brand-200: #99C3FF;
  --color-brand-300: #66A4FF;
  --color-brand-400: #3386FF;
  --color-brand-500: #0057B8;
  --color-brand-600: #0049A3;
  --color-brand-700: #003B8A;
  --color-brand-800: #002D6B;
  --color-brand-900: #001F4D;
  --color-brand-950: #001230;
}
// tailwind.config.js
module.exports = {
  theme: {
    extend: {
      colors: {
        brand: {
          50:  'var(--color-brand-50)',
          100: 'var(--color-brand-100)',
          // ... through 950
        },
      },
    },
  },
}

Now changing the CSS variables at runtime (via JavaScript) instantly recolors your entire UI.

Tailwind v4 configuration

Tailwind CSS v4 moves configuration entirely into CSS using @theme:

@import "tailwindcss";

@theme {
  --color-brand-50:  #E6F0FF;
  --color-brand-100: #CCE1FF;
  --color-brand-200: #99C3FF;
  --color-brand-300: #66A4FF;
  --color-brand-400: #3386FF;
  --color-brand-500: #0057B8;
  --color-brand-600: #0049A3;
  --color-brand-700: #003B8A;
  --color-brand-800: #002D6B;
  --color-brand-900: #001F4D;
  --color-brand-950: #001230;
}

No tailwind.config.js needed. The --color-brand-* variables are automatically available as utility classes (bg-brand-500, text-brand-700, etc.).


Dark Mode Shades

Dark mode does not invert your color scale โ€” it reverses which shades you use. The same scale works for both light and dark mode; you just swap which end of the scale handles backgrounds and which handles text.

The inversion principle

Role Light Mode Dark Mode
Page background brand-50 brand-950
Surface/card background brand-100 brand-900
Subtle border brand-200 brand-800
Muted text brand-400 brand-600
Body text brand-700 brand-300
Heading text brand-900 brand-100
Filled button brand-500 brand-500
Button hover brand-600 brand-400

The filled button color (brand-500) stays the same in both modes โ€” it is the anchor point. Everything around it flips: light backgrounds become dark backgrounds, dark text becomes light text.

Implementing with Tailwind's dark mode

<!-- Background: light-50 in light, dark-950 in dark -->
<div class="bg-brand-50 dark:bg-brand-950">

  <!-- Card: light-100 in light, dark-900 in dark -->
  <div class="bg-brand-100 dark:bg-brand-900 rounded-lg p-6">

    <!-- Heading: dark-900 text in light, light-100 in dark -->
    <h2 class="text-brand-900 dark:text-brand-100">Card Title</h2>

    <!-- Body text: dark-700 in light, light-300 in dark -->
    <p class="text-brand-700 dark:text-brand-300">Card content goes here.</p>

    <!-- Button: always brand-500, hover shifts direction per mode -->
    <button class="bg-brand-500 hover:bg-brand-600 dark:hover:bg-brand-400 text-white">
      Action
    </button>

  </div>
</div>

Generating a separate dark palette

For some design systems, especially those with significant visual separation between light and dark mode, you may want to generate a separate "dark" scale. This could be:

  • A slightly warmer or cooler version of the same hue (more saturated for dark mode, since dark backgrounds need more vivid colors to look equivalent)
  • A complementary hue that works better against dark backgrounds

Generate both scales with the Shade Generator and define them as separate tokens:

:root {
  /* Light mode scale */
  --color-brand-500: #0057B8;
}

[data-theme="dark"] {
  /* Dark mode scale (slightly more saturated) */
  --color-brand-500: #3386FF;
}

Common Custom Scale Scenarios

Matching a brand color exactly

Many brand guidelines specify a single Pantone or hex code. If your brand color is #E63946 (a vivid red), generate the scale anchored at 500. Your brand red becomes brand-500, and you get the full range for design flexibility.

Adding a warm neutral gray

Default gray scales in Tailwind are cool-leaning. To create a warm gray that harmonizes with an orange or red primary, generate a shade scale for a desaturated warm color like #8B7355, then use it as your neutral gray. The slight warmth creates visual coherence with your primary.

Creating semantic color scales

Your design system likely needs semantic scales:

  • Success: Generate from a green like #16A34A
  • Warning: Generate from an amber like #D97706
  • Error/Danger: Generate from a red like #DC2626
  • Info: Generate from a sky blue like #0284C7

Each becomes a named scale in your config (success, warning, error, info) alongside your brand primary and neutral scales.


Key Takeaways

  • Tailwind's 50โ€“950 shade system provides 11 perceptually spaced lightness steps, from near-white to near-black, designed to cover every UI use case.
  • ColorFYI's Shade Generator converts any single hex code into a complete Tailwind-ready scale using a perceptually uniform algorithm.
  • Extend tailwind.config.js using theme.extend.colors to add custom scales without losing Tailwind's defaults; use @theme in Tailwind v4.
  • Use CSS custom properties (var(--color-brand-500)) for runtime theme switching and white-label applications.
  • Dark mode does not need a different color โ€” it uses the same scale inverted: light shades become backgrounds, dark shades become text.
  • Generate separate scales for your primary, neutral/gray, and semantic (success, warning, error, info) colors to build a complete design system.
  • Use the numeric naming convention consistently so developers know exactly which shade to reach for: 600 for hover states, 700 for accessible text on white, 100 for subtle backgrounds.

Related Colors

Related Brands

Related Tools