Color Theory & Application
Color drives emotion, directs attention, and communicates meaning faster than text. A well-chosen palette makes a product feel professional and trustworthy. A poor one makes it feel cheap or confusing, even if everything else is well-designed.
The 60-30-10 Rule
The most reliable formula for color distribution. It creates balance without requiring design intuition.
┌─────────────────────────────────────────────────────┐
│ │
│ 60% DOMINANT │
│ (Background, large surfaces) │
│ │
│ ┌─────────────────────────────┐ │
│ │ │ │
│ │ 30% SECONDARY │ │
│ │ (Cards, sidebars, nav) │ │
│ │ │ │
│ │ ┌─────────────┐ │ │
│ │ │ 10% ACCENT │ │ │
│ │ │ (CTAs, links)│ │ │
│ │ └─────────────┘ │ │
│ └─────────────────────────────┘ │
└─────────────────────────────────────────────────────┘
In practice:
| Ratio | Role | Typical Usage | Example (Light Theme) |
|---|---|---|---|
| 60% | Dominant | Page background, large areas | White (#FFFFFF) or off-white (#F8F9FA) |
| 30% | Secondary | Cards, sidebars, input backgrounds, sections | Light gray (#F1F3F5) or white on gray bg |
| 10% | Accent | Buttons, links, active states, icons | Brand blue (#0066CC) |
Common mistake: Using the accent color too much. If your brand color covers 30%+ of the screen, it's overwhelming. The accent is powerful because it's rare.
Color Psychology
Color associations are culturally influenced but these hold broadly for Western audiences:
| Color | Associations | Common Use | Examples |
|---|---|---|---|
| Blue | Trust, security, calm, professionalism | Banking, healthcare, corporate, tech | Facebook, PayPal, Salesforce |
| Green | Growth, nature, success, money | Finance, eco-friendly, confirmations | Robinhood, Spotify, WhatsApp |
| Red | Urgency, passion, danger, energy | Errors, sales, alerts, food | YouTube, Netflix, Coca-Cola |
| Orange | Energy, enthusiasm, warmth | CTAs, warnings, playful brands | Amazon (button), HubSpot |
| Yellow | Optimism, attention, caution | Highlights, warnings, casual brands | Snapchat, Post-it, warning signs |
| Purple | Luxury, creativity, wisdom | Premium products, creative tools | Twitch, Cadbury, Hallmark |
| Black | Elegance, power, sophistication | Luxury brands, typography-heavy | Apple, Nike, Chanel |
| White | Clean, minimal, space | Backgrounds, breathing room | Apple, Google, modern SaaS |
| Pink | Playful, youthful, romantic | Consumer products, lifestyle | T-Mobile, Dribbble, Lyft |
| Teal | Calm creativity, modern | SaaS, healthcare, wellness | Canva, TikTok |
Important: Don't choose colors based on psychology alone. Choose based on your brand identity, then check that the psychological associations don't conflict.
Building a Color Palette
Required Palette Colors
Every product needs at minimum:
BRAND COLORS:
Primary: Main brand color (used for CTAs, links, key actions)
Secondary: Supporting brand color (used for secondary elements)
NEUTRAL PALETTE:
Gray-50: Lightest (backgrounds)
Gray-100: Light (card backgrounds, borders)
Gray-200: Light (dividers, disabled backgrounds)
Gray-300: Medium-light (borders, icons)
Gray-400: Medium (placeholder text — check contrast!)
Gray-500: Medium-dark (secondary text)
Gray-600: Dark (body text)
Gray-700: Darker (headings)
Gray-800: Very dark (primary headings)
Gray-900: Darkest (high-emphasis text)
SEMANTIC COLORS:
Success: Green — positive states, confirmations
Warning: Yellow/Orange — caution, non-critical alerts
Error: Red — problems, destructive actions
Info: Blue — informational messages, tips
Generating Color Variants
Each color needs a range from light (for backgrounds) to dark (for text on light backgrounds):
:root {
/* Primary — Blue */
--primary-50: #EBF5FF; /* Backgrounds, selected row highlight */
--primary-100: #CCE5FF; /* Light badge backgrounds */
--primary-200: #99CCFF; /* Light borders */
--primary-300: #66B2FF; /* Icons on light backgrounds */
--primary-400: #3399FF; /* Secondary buttons */
--primary-500: #0066CC; /* Base — primary buttons, links */
--primary-600: #0052A3; /* Hover state */
--primary-700: #003D7A; /* Active/pressed state */
--primary-800: #002952; /* Dark backgrounds */
--primary-900: #001429; /* Darkest — text on light backgrounds */
/* Error — Red */
--error-50: #FFF5F5; /* Error background */
--error-100: #FFE3E3; /* Error badge background */
--error-500: #E03131; /* Error text, icons */
--error-600: #C92A2A; /* Error hover */
--error-700: #A61E1E; /* Error dark text */
/* Success — Green */
--success-50: #F0FFF4;
--success-100: #C6F6D5;
--success-500: #38A169;
--success-600: #2F855A;
--success-700: #276749;
}
Tools for generating variants:
- Tailwind CSS Colors: pre-built palettes with 50-950 shades
- Realtime Colors (realtimecolors.com): preview palette on a live page
- Coolors (coolors.co): generate harmonious palettes
- Huemint: AI-powered palette generation
- ColorBox by Lyft: systematic shade generation
Color Harmony Methods
| Method | Description | When to Use |
|---|---|---|
| Monochromatic | One hue, different lightness/saturation | Safe, cohesive. Best for minimalist brands. |
| Complementary | Two hues opposite on the color wheel | High contrast. Good for accent + primary. |
| Analogous | 2-3 adjacent hues on the color wheel | Harmonious, natural. Low contrast. |
| Triadic | Three hues equally spaced (120° apart) | Vibrant, playful. Hard to balance. |
| Split-complementary | One hue + two adjacent to its complement | Less tension than complementary. Versatile. |
For most product interfaces, monochromatic + one accent or complementary palettes are the safest choices. Save triadic and complex harmonies for brand/marketing work.
Contrast Requirements (WCAG 2.2)
These aren't guidelines, they're legal requirements in many jurisdictions. Get them right.
| Element | Minimum Ratio (AA) | Enhanced Ratio (AAA) |
|---|---|---|
| Normal text (<18pt) | 4.5:1 | 7:1 |
| Large text (18pt+ or 14pt+ bold) | 3:1 | 4.5:1 |
| UI components (borders, icons) | 3:1 | N/A |
| Non-text graphics | 3:1 | N/A |
Common Contrast Failures
| Situation | Typical Ratio | Fix |
|---|---|---|
| Light gray text on white (#999 on #FFF) | 2.8:1 (FAIL) | Darken to #767676 or darker |
| Placeholder text (#BBB on #FFF) | 1.9:1 (FAIL) | Use #767676 minimum, or use visible labels instead |
| White text on yellow button | Often <3:1 (FAIL) | Use dark text on yellow, or darken the yellow |
| Blue link on blue background | Varies, often FAIL | Ensure underline or sufficient contrast |
| Disabled text (#CCC on #FFF) | 1.6:1 (technically exempt) | Still try for 2:1+ minimum for usability |
Tools for checking contrast:
- WebAIM Contrast Checker (webaim.org/resources/contrastchecker)
- Stark (Figma/Sketch plugin)
- Colour Contrast Analyser (desktop app)
- Chrome DevTools: Inspect element, the color picker shows contrast ratio
Testing Shortcut
Memorize this: #767676 on #FFFFFF = exactly 4.5:1. Any gray darker than #767676 passes for normal text on white.
Semantic Color Usage
Colors should communicate meaning consistently:
| Meaning | Color | Usage | Never Use For |
|---|---|---|---|
| Success/Positive | Green | Confirmations, saved states, completed steps | Errors, warnings |
| Error/Danger | Red | Validation errors, destructive actions, alerts | Success states, brand decoration |
| Warning/Caution | Yellow/Amber | Non-blocking alerts, expiring items | Errors (too subtle), success |
| Info/Neutral | Blue | Tips, informational banners, help text | Errors (confusing with links) |
| Disabled | Gray (lower opacity) | Inactive elements, unavailable actions | Active or important elements |
Critical rule: Never use color as the only indicator of meaning. Always pair with text, icons, or patterns. 8% of men are colorblind.
BAD (color only):
┌────────────────┐ ┌────────────────┐ ┌────────────────┐
│ Green border │ │ Yellow border │ │ Red border │
│ (passed) │ │ (warning) │ │ (failed) │
└────────────────┘ └────────────────┘ └────────────────┘
GOOD (color + icon + text):
┌────────────────┐ ┌────────────────┐ ┌────────────────┐
│ ✓ Passed │ │ ⚠ Warning │ │ ✗ Failed │
│ Green border │ │ Yellow border │ │ Red border │
└────────────────┘ └────────────────┘ └────────────────┘
Dark Mode
Dark mode isn't "invert all the colors." It requires deliberate design.
Dark Mode Principles
| Principle | Light Mode | Dark Mode |
|---|---|---|
| Background | White (#FFFFFF) | Not black; use #121212 to #1E1E1E |
| Surface/Cards | Light gray (#F5F5F5) | Slightly lighter than bg (#1E1E1E to #2C2C2C) |
| Primary text | Near-black (#1A1A1A) | Off-white (#E0E0E0 to #F0F0F0) |
| Secondary text | Dark gray (#666666) | Medium gray (#A0A0A0 to #B0B0B0) |
| Accent colors | Full saturation | Desaturate by 10-20% |
| Contrast | Standard | Slightly reduce (avoid glowing white text on dark) |
| Elevation | Shadows get darker | Surfaces get lighter (lighter = higher elevation) |
Dark Mode CSS
/* Using CSS custom properties for easy theming */
:root {
--bg-primary: #FFFFFF;
--bg-surface: #F5F5F5;
--text-primary: #1A1A1A;
--text-secondary: #666666;
--accent: #0066CC;
}
@media (prefers-color-scheme: dark) {
:root {
--bg-primary: #121212;
--bg-surface: #1E1E1E;
--text-primary: #E0E0E0;
--text-secondary: #A0A0A0;
--accent: #4D9FFF; /* Lighter/desaturated for dark bg */
}
}
Dark Mode Mistakes
| Mistake | Why It Fails | Fix |
|---|---|---|
| Pure black (#000) background | Too harsh, causes "halation" (bright text blooms) | Use #121212 - #1A1A1A |
| Pure white (#FFF) text | Too much contrast, eye strain | Use #E0E0E0 - #F0F0F0 |
| Same accent color as light mode | Saturated colors vibrate on dark backgrounds | Lighten and desaturate by 10-20% |
| Using shadows for elevation | Shadows invisible on dark backgrounds | Use lighter surface colors for elevation |
| Not testing images | Images with white backgrounds look wrong | Add subtle rounded corners and borders, or use transparent PNGs |
Color in Data Visualization
When using color to represent data, follow these guidelines:
| Guideline | Explanation |
|---|---|
| Sequential palette | Light → dark for low → high values (one hue) |
| Diverging palette | Two hues meeting at neutral for above/below a midpoint |
| Categorical palette | Distinct hues for different categories (max 6-8) |
| Colorblind-safe | Avoid red-green distinctions. Use blue-orange instead. |
| Meaningful defaults | Red = bad, green = good, gray = neutral |
Sequential: ░░░░ ▒▒▒▒ ▓▓▓▓ ████ (light blue → dark blue)
Diverging: ████ ▓▓▓▓ ░░░░ ▓▓▓▓ ████ (red → white → blue)
Categorical: ████ ████ ████ ████ ████ (5 distinct hues)
Common Mistakes
| Mistake | Impact | Fix |
|---|---|---|
| Too many colors | Overwhelming, unprofessional | Stick to 60-30-10. Use grays for most things. |
| No semantic consistency | Red sometimes means error, sometimes means "sale" | Define semantic meanings and never break them |
| Ignoring colorblindness | 8% of male users can't distinguish red/green | Always pair color with icons or text. Test with colorblind simulators. |
| Brand color for everything | Key actions blend in when everything is branded | Use brand color sparingly, primarily for CTAs and links |
| Skipping contrast testing | Text unreadable in certain conditions | Check every text/background combination with WebAIM |
| Different blues for links vs. buttons | Users can't tell what's clickable | Use one primary blue for all interactive elements |
Key Takeaways
- Apply 60-30-10: most of the screen is neutral, 30% secondary, 10% accent.
- Build a complete palette: brand primary, neutral grays (50-900), semantic colors (success, warning, error, info).
- Check contrast for every text/background pair. Memorize: #767676 on white = 4.5:1 minimum.
- Never use color as the only way to communicate meaning. Always supplement with text or icons.
- Dark mode isn't inverted light mode. Use off-black backgrounds, desaturated accents, and lighter surfaces for elevation.
- Keep it simple: 1-2 brand colors, a neutral gray palette, and 4 semantic colors covers 99% of UI needs.