Skip to main content

Building Color Palettes

A color palette is the complete set of colors your product uses. A well-structured palette covers every need — branding, interactive states, backgrounds, text, borders, errors, and successes — while remaining manageable and consistent. This lesson walks through building a production-ready palette from scratch.

Palette Structure

A web application palette typically includes these categories:

Primary Color

Your brand's main color. It appears on primary buttons, active navigation items, links, and key UI accents. You need the base shade plus lighter and darker variants for hover states, backgrounds, and borders.

Secondary Color

A complementary or supporting color for secondary actions and less prominent UI elements. Not every product needs one — some designs work beautifully with a single primary color plus neutrals.

Accent Color

An optional high-contrast color for drawing attention to specific elements — badges, notifications, or promotional banners.

Neutral Scale

The most used colors in your palette. Neutrals cover backgrounds, text, borders, dividers, and disabled states. You typically need 8 to 10 shades from near-white to near-black.

Semantic Colors

Colors tied to meaning: error (red), success (green), warning (yellow/amber), and info (blue). These are functional, not decorative.

Generating a Full Scale

Start with your primary color and generate a 10-step scale from lightest (50) to darkest (900). Here is a blue primary scale:

:root {
  --primary-50:  #eff6ff;
  --primary-100: #dbeafe;
  --primary-200: #bfdbfe;
  --primary-300: #93c5fd;
  --primary-400: #60a5fa;
  --primary-500: #3b82f6;  /* Base */
  --primary-600: #2563eb;
  --primary-700: #1d4ed8;
  --primary-800: #1e40af;
  --primary-900: #1e3a8a;
}

The key principle: lighter shades decrease saturation and increase lightness, while darker shades increase saturation slightly and decrease lightness. Do not just add white or black — that creates muddy, lifeless colors.

Building a Neutral Scale

Pure gray (equal R, G, B) often feels cold and lifeless. Most design systems tint their neutrals slightly toward the primary color for cohesion:

:root {
  /* Neutrals tinted slightly toward blue */
  --neutral-50:  #f8fafc;
  --neutral-100: #f1f5f9;
  --neutral-200: #e2e8f0;
  --neutral-300: #cbd5e1;
  --neutral-400: #94a3b8;
  --neutral-500: #64748b;
  --neutral-600: #475569;
  --neutral-700: #334155;
  --neutral-800: #1e293b;
  --neutral-900: #0f172a;
}

Use these neutrals for text (neutral-900 for headings, neutral-600 for body, neutral-400 for placeholder text), backgrounds (neutral-50, neutral-100), and borders (neutral-200, neutral-300).

Semantic Color Scales

Semantic colors need at least three values: a light background, the base color, and dark text that is readable on the light background:

:root {
  /* Error */
  --error-bg: #fef2f2;
  --error: #dc2626;
  --error-text: #991b1b;

  /* Success */
  --success-bg: #f0fdf4;
  --success: #16a34a;
  --success-text: #166534;

  /* Warning */
  --warning-bg: #fffbeb;
  --warning: #d97706;
  --warning-text: #92400e;

  /* Info */
  --info-bg: #eff6ff;
  --info: #2563eb;
  --info-text: #1e40af;
}

These triples let you build alert banners, form validation messages, and status indicators with proper contrast.

Tools for Palette Generation

ToolWhat It DoesURL
Realtime ColorsPreview your palette on a realistic website layoutrealtimecolors.com
CoolorsGenerate and explore harmonious palettescoolors.co
Tailwind CSS ColorsA battle-tested set of color scalestailwindcss.com/docs/colors
HSL Color PickerFine-tune individual colors with HSL slidershslpicker.com
Contrast CheckerVerify text-to-background contrast ratioswebaim.org/resources/contrastchecker

Dark Mode Palettes

Dark mode is not just inverting your light palette. Effective dark mode requires:

  • Elevated surfaces instead of shadows — In dark mode, lighter surfaces feel "closer." Use neutral-800 for cards on a neutral-900 background.
  • Reduced saturation — Vivid colors that look great on white can feel harsh on dark backgrounds. Reduce saturation by 10-20%.
  • Proper text contrast — Use neutral-100 or neutral-200 for body text on dark backgrounds, not pure white (#ffffff), which causes eye strain.
.dark {
  --color-background: var(--neutral-900);
  --color-surface: var(--neutral-800);
  --color-text: var(--neutral-100);
  --color-text-secondary: var(--neutral-400);
  --color-primary: #60a5fa; /* Lighter, less saturated blue */
}

Common Mistakes

  • Too many colors — If your palette has 40+ named colors, it is too complex to use consistently. Aim for a primary scale, neutrals, and semantics.
  • Ignoring contrast — A beautiful color is useless if text on top of it is unreadable. Always check contrast ratios.
  • Forgetting interactive states — Every color used on an interactive element needs hover, active, focus, and disabled variants.
  • Pure black backgrounds#000000 as a background is harsh. Use a very dark neutral like #0f172a instead.