Color Theory for Developers
/ 4 min read
Table of Contents
Most developers pick colors one of two ways: copying a popular site, or using whatever the default Tailwind palette looks like. Both work. Neither teach you why those colors work.
This guide covers the 20% of color theory that handles 80% of real-world UI decisions.
The Three Properties
Every color has three properties:
- Hue — The color itself (red, blue, green)
- Saturation — How vivid or muted it is
- Lightness — How bright or dark it is
In CSS HSL notation:
/* hsl(hue, saturation, lightness) */color: hsl(210, 80%, 50%); /* Vivid blue */color: hsl(210, 20%, 50%); /* Muted blue */color: hsl(210, 80%, 90%); /* Light blue */color: hsl(210, 80%, 15%); /* Dark blue */Understanding HSL is the single most useful color skill for developers. When you need a lighter version of your brand color, increase lightness. Need a background tint? Decrease saturation and increase lightness. Need a hover state? Shift lightness by 5-10%.
Building a Palette
A functional UI palette needs exactly five groups:
1. Neutral Scale (60% of your UI)
Your neutral scale handles text, backgrounds, borders, and shadows. It should have 9-11 steps from near-white to near-black.
:root { --neutral-50: hsl(210, 10%, 98%); /* Page background */ --neutral-100: hsl(210, 10%, 96%); /* Card background */ --neutral-200: hsl(210, 10%, 90%); /* Borders */ --neutral-300: hsl(210, 10%, 82%); /* Disabled */ --neutral-400: hsl(210, 10%, 65%); /* Placeholder text */ --neutral-500: hsl(210, 10%, 46%); /* Secondary text */ --neutral-600: hsl(210, 10%, 35%); /* Icons */ --neutral-700: hsl(210, 10%, 25%); /* Body text */ --neutral-800: hsl(210, 10%, 15%); /* Headings */ --neutral-900: hsl(210, 10%, 8%); /* High contrast */}Key insight: Your neutrals shouldn’t be pure gray. Add a slight hue (blue-gray for tech, warm gray for editorial) to give them personality.
2. Primary Color (20% of your UI)
Your brand color. Used for buttons, links, active states, and key UI elements.
Pick one hue and generate a 9-step scale by varying saturation and lightness:
:root { --primary-50: hsl(170, 60%, 95%); --primary-100: hsl(170, 60%, 88%); --primary-200: hsl(170, 60%, 75%); --primary-300: hsl(170, 60%, 62%); --primary-400: hsl(170, 60%, 50%); /* Default */ --primary-500: hsl(170, 65%, 42%); --primary-600: hsl(170, 70%, 35%); /* Hover */ --primary-700: hsl(170, 75%, 28%); --primary-800: hsl(170, 80%, 20%); --primary-900: hsl(170, 85%, 12%);}3. Semantic Colors (15% of your UI)
Fixed meanings across all products:
| Color | Meaning | Example HSL |
|---|---|---|
| Green | Success, positive | hsl(145, 65%, 42%) |
| Red | Error, destructive | hsl(0, 72%, 51%) |
| Yellow | Warning, caution | hsl(45, 93%, 47%) |
| Blue | Info, neutral action | hsl(210, 80%, 50%) |
Don’t reinvent these. Users have spent decades learning that red means danger and green means go.
4. Accent Color (5% of your UI)
Optional. A secondary color for highlights, tags, or decorative elements. Choose something complementary to your primary (roughly opposite on the color wheel).
The 60-30-10 Rule
The classic interior design rule works for UI too:
- 60% neutral — Backgrounds, text, borders
- 30% primary — Navigation, buttons, links
- 10% accent — Highlights, notifications, badges
This ratio prevents visual chaos. When a UI feels “off,” it’s usually because the proportions are wrong — too much primary, or accent competing with primary.
Contrast and Accessibility
WCAG requires minimum contrast ratios:
- 4.5:1 for normal text (< 18px)
- 3:1 for large text (≥ 18px bold or ≥ 24px)
- 3:1 for UI components and graphics
Practical rules:
Light backgrounds: Use neutral-700 or darker for body textDark backgrounds: Use neutral-200 or lighter for body textPrimary on white: Test at 600-700 weight (darker end)White on primary: Test at 400-500 weight (middle-bright)Dark Mode in 30 Seconds
Don’t invert your colors. Instead:
- Swap your neutral scale (50 ↔ 900, 100 ↔ 800, etc.)
- Reduce primary saturation by 10-15%
- Increase primary lightness by 10-15%
- Lower background contrast (don’t use pure black — use neutral-900)
.dark { --primary-400: hsl(170, 50%, 60%); /* Was 60% sat, 50% light */ --bg: var(--neutral-900); /* Not #000000 */}Pure black backgrounds cause eye strain. A slight tint is always better.
Tools
- Realtime Colors — Live preview of your palette on a mock UI
- Contrast Checker — WCAG ratio calculator
- Huetone — Build perceptually uniform color scales
- Tailwind CSS Colors — Steal their scales as starting points
Color theory doesn’t have to be complex. Neutral scale + one primary + semantic colors covers 95% of what you’ll build. Master HSL, respect contrast ratios, and you’ll make better color decisions than most designers.