บทเรียนแนะนำ

Tailwind CSS Colors: คู่มือระบบเฉดฉบับสมบูรณ์

อ่าน 7 นาที

Tailwind CSS ships with one of the most widely referenced color systems in web development. Its shade naming convention — numbers from 50 to 950 — has become an industry standard that influences design tools, other CSS frameworks, and custom design systems far beyond projects that actually use Tailwind. Understanding how this system is structured, how to extend it, and how it evolved in Tailwind v4 gives you both a practical skill and a mental model for color scale design.

Default Palette Overview

The Tailwind default palette contains 22 color families, each with 11 shades (50 through 950). A few select colors — black, white, transparent, and inherit — are also available as single-value utilities.

The core color families in the default palette are:

Family Hue Character Lightest (50) Darkest (950)
slate Cool gray-blue #F8FAFC #020617
gray Neutral gray #F9FAFB #030712
zinc Slightly warm gray #FAFAFA #09090B
neutral Pure gray #FAFAFA #0A0A0A
stone Warm beige-gray #FAFAF9 #0C0A09
red Red #FEF2F2 #450A0A
orange Orange #FFF7ED #431407
amber Yellow-orange #FFFBEB #451A03
yellow Yellow #FEFCE8 #422006
lime Yellow-green #F7FEE7 #1A2E05
green Green #F0FDF4 #052E16
emerald Vivid green #ECFDF5 #022C22
teal Green-cyan #F0FDFA #042F2E
cyan Cyan #ECFEFF #083344
sky Light blue #F0F9FF #082F49
blue Blue #EFF6FF #172554
indigo Blue-violet #EEF2FF #1E1B4B
violet Violet #F5F3FF #2E1065
purple Purple #FAF5FF #3B0764
fuchsia Pink-purple #FDF4FF #4A044E
pink Pink #FDF2F8 #500724
rose Red-pink #FFF1F2 #4C0519

The gray families (slate, gray, zinc, neutral, stone) differ primarily in their undertone. slate has a blue-gray cast, stone leans warm, and neutral is the most purely achromatic. Choosing the right gray family for a project matters more than many developers realize — slate grays feel different from stone grays in a full UI.

Shade Naming Convention: 50–950

The numbering system follows a consistent rule: higher numbers are darker. The scale is not perfectly linear — Tailwind's team hand-tuned the steps for perceptual uniformity rather than mathematical uniformity — but the relationship is reliable:

Shade Primary Use
50 Subtle backgrounds, hover states, table row stripes
100 Light badges, notification backgrounds, code block backgrounds
200 Borders in light mode, secondary disabled states
300 Icons and secondary text on white backgrounds, subtle borders
400 Placeholder text, decorative elements
500 The "identity" shade — most recognizable version of the color
600 Primary button backgrounds, interactive element defaults
700 Hover state for interactive elements at 600
800 Text on white, dark icon fills
900 Heading text, high-contrast text, dark mode surfaces
950 Added in Tailwind v3.3 — near-black with hue tint, dark mode deep backgrounds

The Tailwind default blue-500 is #3B82F6 — a medium, fully-saturated blue that is the "canonical" Tailwind blue. blue-600 (#2563EB) is the standard hover state for a blue button. blue-100 (#DBEAFE) is the background for a blue badge. These relationships are consistent across every color family in the palette.

The 950 Addition

Tailwind v3.3 added the 950 shade to every color family. Before that addition, 900 was the darkest option, which was too light for dark mode backgrounds in some color families. The 950 shades fill that gap — they are very dark but retain a visible tint of the parent hue. For example, blue-950 (#172554) reads as dark navy, not pure black, making it useful for dark-mode surfaces that maintain brand character.

Adding Custom Colors

For projects with brand colors not covered by the default palette, Tailwind's config allows you to add custom color families. The approach differs between Tailwind v3 and v4.

Tailwind v3: tailwind.config.js

In v3, custom colors go in the extend.colors object to add alongside the defaults, or the colors object to replace them:

// tailwind.config.js
const colors = require('tailwindcss/colors');

module.exports = {
  theme: {
    extend: {
      colors: {
        // Add a custom brand color family
        brand: {
          50:  '#f0f9ff',
          100: '#e0f2fe',
          200: '#bae6fd',
          300: '#7dd3fc',
          400: '#38bdf8',
          500: '#0ea5e9',  // Primary brand color
          600: '#0284c7',
          700: '#0369a1',
          800: '#075985',
          900: '#0c4a6e',
          950: '#082f49',
        },
        // Or reference an existing family with a new name
        primary: colors.indigo,
        danger: colors.red,
      },
    },
  },
};

After this configuration, you can use classes like bg-brand-500, text-brand-700, border-brand-200, and so on.

Generating a Custom Scale

The challenging part of adding a custom color is generating a full 11-shade scale from a single brand hex value. Doing this by hand — adjusting lightness manually for each step — produces inconsistent results.

The Shade Generator automates this: enter your brand's primary hex and it computes the complete 50–950 scale with perceptually uniform steps, outputting values you can paste directly into your Tailwind config. For example, if your brand primary is #0EA5E9 (a sky blue), the generator produces a full 11-shade scale calibrated to match the lightness curve of Tailwind's native palettes.

Using withOpacityValue for Dynamic Alpha

In Tailwind v3, color utilities support arbitrary opacity via the slash syntax (bg-blue-500/50 for 50% opacity). When defining custom colors in v3, you can make this work by using CSS custom properties with the withOpacityValue pattern:

// tailwind.config.js
module.exports = {
  theme: {
    extend: {
      colors: {
        brand: {
          500: 'rgb(var(--color-brand-500) / <alpha-value>)',
        },
      },
    },
  },
};

Then define the raw channel values in CSS:

:root {
  --color-brand-500: 14 165 233; /* R G B values of #0EA5E9 */
}

This allows bg-brand-500/30 (30% opacity) to work correctly in the generated CSS.

Extending the Palette in Config

Beyond custom color families, the Tailwind config lets you extend the palette with semantic aliases and arbitrary values.

Semantic Aliases

One approach: define your brand colors as semantic aliases that reference the palette:

// tailwind.config.js
const colors = require('tailwindcss/colors');

module.exports = {
  theme: {
    extend: {
      colors: {
        primary: colors.blue,
        secondary: colors.violet,
        success: colors.green,
        warning: colors.amber,
        danger: colors.red,
        neutral: colors.slate,
      },
    },
  },
};

Now bg-primary-500 generates the same CSS as bg-blue-500, but your class names communicate purpose rather than color. This pattern mirrors the semantic naming approach in design tokens — the same class works even if you later decide the primary color should be indigo instead of blue.

Single-Value Semantic Colors

For design systems where you want named colors without the full scale:

module.exports = {
  theme: {
    extend: {
      colors: {
        'brand-primary':    '#0EA5E9',
        'brand-secondary':  '#7C3AED',
        'text-on-primary':  '#FFFFFF',
        'surface-dark':     '#0F172A',
      },
    },
  },
};

Use these as bg-brand-primary, text-text-on-primary, and so on.

Tailwind v4: The CSS Variables Approach

Tailwind v4 introduces a fundamentally different configuration model. Instead of a JavaScript config file, the entire design system is defined in CSS using custom properties and CSS-based configuration.

The @theme Directive

Colors in Tailwind v4 are defined using the @theme directive in your CSS file:

@import "tailwindcss";

@theme {
  /* Redefine or extend the default palette */
  --color-brand-50:   #f0f9ff;
  --color-brand-100:  #e0f2fe;
  --color-brand-200:  #bae6fd;
  --color-brand-300:  #7dd3fc;
  --color-brand-400:  #38bdf8;
  --color-brand-500:  #0ea5e9;
  --color-brand-600:  #0284c7;
  --color-brand-700:  #0369a1;
  --color-brand-800:  #075985;
  --color-brand-900:  #0c4a6e;
  --color-brand-950:  #082f49;
}

Tailwind v4 reads the --color-* custom properties and automatically generates the corresponding utility classes: bg-brand-500, text-brand-700, border-brand-200, etc.

Semantic Colors in v4

The v4 approach makes semantic color aliasing extremely clean because it uses standard CSS custom properties:

@import "tailwindcss";

@theme {
  --color-primary:           var(--color-blue-600);
  --color-primary-hover:     var(--color-blue-700);
  --color-primary-subtle:    var(--color-blue-50);

  --color-success:           var(--color-green-600);
  --color-danger:            var(--color-red-600);
  --color-warning:           var(--color-amber-500);
}

Now bg-primary is a valid Tailwind class — and because it references a CSS custom property, you can override it in a dark mode block or theme selector without touching the Tailwind config:

[data-theme="dark"] {
  --color-primary: var(--color-blue-400);
}

This is the most significant improvement in v4's color system: theming is pure CSS, with no build step required to switch themes.

P3 and OKLCH Colors in v4

Tailwind v4's default palette uses OKLCH values internally for perceptual uniformity. The palette in v4 produces more visually consistent steps across hue — particularly noticeable in warm colors like orange and yellow, where earlier palettes had uneven lightness steps.

When using the Color Converter to generate OKLCH values for your brand colors, you can slot those directly into the @theme block:

@theme {
  /* Brand color defined in OKLCH for wide-gamut P3 display support */
  --color-brand-500: oklch(60% 0.18 220);
}

Modern browsers on wide-gamut displays (most MacBooks, iPhones) will render this in the P3 color space — producing a noticeably more vivid blue than the sRGB-clamped equivalent.

Practical Color Selection Tips

Combining Families Effectively

Tailwind's gray families were designed to complement specific accent colors. Some common pairings:

  • slate + blue/indigo — cool, corporate, slightly techy
  • stone + amber/orange — warm, artisanal, human
  • zinc + violet/purple — neutral, modern, slightly dark
  • neutral + any — the most versatile gray, works with everything

Mixing grays from different families in the same UI (e.g., slate-100 for one background and zinc-200 for another) produces subtle visual inconsistency. Commit to one gray family per project.

The 100/700 Text-on-Background Rule

A reliable contrast-safe combination in Tailwind: use shade 700 text on a shade 100 background within the same family. For example, text-blue-700 on bg-blue-100 produces a legible blue badge that clears WCAG AA. Use the Contrast Checker to verify any non-standard combination.

Dark Mode Shade Mapping

A common pattern for dark mode in Tailwind is to invert the shade scale — what was 700 in light mode becomes 300 in dark mode:

<p class="text-gray-700 dark:text-gray-300">
  Body text — dark gray in light mode, light gray in dark mode
</p>

<div class="bg-gray-100 dark:bg-gray-800">
  Subtle background — barely gray in light, dark surface in dark
</div>

This symmetry works because the Tailwind scale is designed so that 100+900=1000 and 200+800=1000 — the shade pairs are mirror images in terms of perceived lightness.

Key Takeaways

  • Tailwind's 22 color families each span 11 shades from 50 (near white) to 950 (near black), with 500 as the canonical "identity" shade and 600 as the default interactive state.
  • Choose one gray family (slate, gray, zinc, neutral, or stone) per project and use it consistently — mixing gray families creates subtle visual inconsistency.
  • Custom color families are added via extend.colors in Tailwind v3 or @theme in v4. The Shade Generator generates a full 50–950 scale from any single brand hex value.
  • In Tailwind v4, colors are CSS custom properties under @theme, enabling pure-CSS theming without rebuild — override semantic color variables in a [data-theme="dark"] block.
  • Semantic aliases (primary: colors.blue) make class names communicate purpose rather than appearance, surviving future brand color changes with no class-name refactoring.
  • The Color Converter provides OKLCH equivalents for any hex color — useful for v4 wide-gamut color definitions that take advantage of P3 displays.

สีที่เกี่ยวข้อง

แบรนด์ที่เกี่ยวข้อง

เครื่องมือที่เกี่ยวข้อง