Skip to main content
โšก Calmops

Color Theory for Web Design: Practical Implementation Guide

Color is one of the most powerful tools in web design. It can evoke emotions, establish hierarchy, guide attention, and create memorable experiences. This guide covers color theory fundamentals and practical implementation for the web.

Color Models for Web

RGB (Red, Green, Blue)

The standard color model for digital displays:

/* RGB values: 0-255 */
color: rgb(255, 0, 0);      /* Red */
color: rgb(0, 255, 0);       /* Green */
color: rgb(0, 0, 255);       /* Blue */
color: rgb(255, 255, 255);   /* White */
color: rgb(0, 0, 0);         /* Black */

RGBA (RGB with Alpha)

Add transparency:

/* Alpha: 0 (transparent) to 1 (opaque) */
color: rgba(255, 0, 0, 0.5);   /* Semi-transparent red */
background: rgba(0, 0, 0, 0.8); /* Semi-transparent black */

HSL (Hue, Saturation, Lightness)

More intuitive for humans:

/* Hue: 0-360 (color wheel) */
/* Saturation: 0-100% (gray to vivid) */
/* Lightness: 0-100% (black to white) */

color: hsl(0, 100%, 50%);      /* Pure red */
color: hsl(120, 100%, 50%);    /* Pure green */
color: hsl(240, 100%, 50%);    /* Pure blue */

/* Easy to adjust */
color: hsl(200, 80%, 50%);    /* Blue with 80% saturation */
color: hsl(200, 80%, 30%);    /* Darker version */
color: hsl(200, 80%, 70%);    /* Lighter version */

HSLA (HSL with Alpha)

color: hsla(200, 80%, 50%, 0.5); /* Semi-transparent blue */

Modern Color Functions

CSS now supports modern color functions:

/* Relative colors (CSS Color Level 5) */
color: oklch(70% 0.15 240);   /* Modern, perceptually uniform */
color: oklch(70% 0.15 240 / 50%); /* With alpha */

/* Lighten/Darken */
color: light-dark(white, black);
color: oklch(from #3498db 70% l h); /* Extract components */

/* Mix colors */
color: color-mix(in srgb, red, blue); /* Purple */
color: color-mix(in oklch, red 30%, blue); /* 30% red, 70% blue */

Building Color Palettes

The 60-30-10 Rule

A classic palette structure:

:root {
  /* 60% - Dominant color (backgrounds, large areas) */
  --color-primary: #2563eb;
  
  /* 30% - Secondary color (supporting elements) */
  --color-secondary: #64748b;
  
  /* 10% - Accent color (calls to action, highlights) */
  --color-accent: #f59e0b;
}

Creating a Blue Palette

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

Generating Palettes

Use HSL for easy palette generation:

:root {
  /* Base hue for primary color (200 = blue) */
  --hue-primary: 200;
  --hue-secondary: 280; /* Purple */
  --hue-accent: 25;     /* Orange */
  
  /* Full saturation scale */
  --primary-50: hsl(var(--hue-primary), 90%, 95%);
  --primary-100: hsl(var(--hue-primary), 85%, 90%);
  --primary-200: hsl(var(--hue-primary), 80%, 80%);
  --primary-300: hsl(var(--hue-primary), 70%, 70%);
  --primary-400: hsl(var(--hue-primary), 60%, 60%);
  --primary-500: hsl(var(--hue-primary), 50%, 50%);
  --primary-600: hsl(var(--hue-primary), 50%, 40%);
  --primary-700: hsl(var(--hue-primary), 50%, 30%);
  --primary-800: hsl(var(--hue-primary), 50%, 20%);
  --primary-900: hsl(var(--hue-primary), 50%, 10%);
}

Color Accessibility

WCAG Contrast Requirements

Ensure text is readable:

/* WCAG AA - Minimum contrast */
/* Normal text: 4.5:1 */
/* Large text (18px+ or 14px bold): 3:1 */

/* Function to check contrast */
function getContrastColor(hexColor) {
  // Calculate relative luminance
  // Return black or white based on contrast
}

/* Example: Use for dynamic text color */
.text {
  color: var(--text-color);
  background: var(--bg-color);
}

Automatic Contrast Solutions

/* Use semantic colors that work on both backgrounds */
:root {
  --text-primary: #1a1a2e;     /* Works on light */
  --text-secondary: #64748b;
  --text-inverse: #f8fafc;     /* Works on dark */
}

/* Dark mode adjustments */
@media (prefers-color-scheme: dark) {
  :root {
    --text-primary: #f8fafc;
    --text-secondary: #94a3b8;
  }
}

Accessible Button Colors

.btn-primary {
  background-color: #2563eb;
  color: white;
  /* Contrast: 4.6:1 - passes WCAG AA */
}

.btn-secondary {
  background-color: #e2e8f0;
  color: #1e293b;
  /* Contrast: 8:1 - passes WCAG AAA */
}

Implementing with CSS Custom Properties

Base Color System

:root {
  /* Neutral colors */
  --gray-50: #f8fafc;
  --gray-100: #f1f5f9;
  --gray-200: #e2e8f0;
  --gray-300: #cbd5e1;
  --gray-400: #94a3b8;
  --gray-500: #64748b;
  --gray-600: #475569;
  --gray-700: #334155;
  --gray-800: #1e293b;
  --gray-900: #0f172a;
  --gray-950: #020617;
  
  /* Semantic colors */
  --color-bg: var(--gray-50);
  --color-bg-alt: var(--gray-100);
  --color-text: var(--gray-900);
  --color-text-muted: var(--gray-500);
  --color-border: var(--gray-200);
  --color-primary: #2563eb;
  --color-primary-hover: #1d4ed8;
  --color-success: #16a34a;
  --color-warning: #ca8a04;
  --color-error: #dc2626;
}

Semantic Color Names

:root {
  /* Surfaces */
  --surface-primary: white;
  --surface-secondary: var(--gray-100);
  --surface-elevated: white;
  
  /* Text */
  --text-on-primary: white;
  --text-on-secondary: var(--gray-900);
  --text-on-accent: white;
  
  /* Interactive */
  --interactive-default: var(--color-primary);
  --interactive-hover: var(--color-primary-hover);
  --interactive-active: #1e40af;
  --interactive-disabled: var(--gray-300);
  
  /* Focus */
  --focus-ring: rgba(37, 99, 235, 0.4);
}

Dark Mode Implementation

CSS-Only Dark Mode

:root {
  --bg-primary: #ffffff;
  --bg-secondary: #f8fafc;
  --text-primary: #0f172a;
  --text-secondary: #475569;
  --border-color: #e2e8f0;
}

/* Automatic dark mode */
@media (prefers-color-scheme: dark) {
  :root {
    --bg-primary: #0f172a;
    --bg-secondary: #1e293b;
    --text-primary: #f8fafc;
    --text-secondary: #94a3b8;
    --border-color: #334155;
  }
}

Manual Toggle

[data-theme="light"] {
  --bg-primary: #ffffff;
  --bg-secondary: #f8fafc;
  --text-primary: #0f172a;
}

[data-theme="dark"] {
  --bg-primary: #0f172a;
  --bg-secondary: #1e293b;
  --text-primary: #f8fafc;
}
// Toggle theme
const toggle = document.getElementById('theme-toggle');
toggle.addEventListener('click', () => {
  const current = document.documentElement.getAttribute('data-theme');
  const next = current === 'dark' ? 'light' : 'dark';
  document.documentElement.setAttribute('data-theme', next);
  localStorage.setItem('theme', next);
});

// Load saved theme
const saved = localStorage.getItem('theme');
if (saved) {
  document.documentElement.setAttribute('data-theme', saved);
}

Color in Practice

Status Colors

:root {
  /* Use meaningful saturation/lightness for status */
  --success-bg: #dcfce7;
  --success-text: #166534;
  --success-border: #bbf7d0;
  
  --warning-bg: #fef9c3;
  --warning-text: #854d0e;
  --warning-border: #fde047;
  
  --error-bg: #fee2e2;
  --error-text: #991b1b;
  --error-border: #fecaca;
  
  --info-bg: #dbeafe;
  --info-text: #1e40af;
  --info-border: #bfdbfe;
}

/* Usage */
.alert {
  padding: 1rem;
  border-radius: 0.5rem;
  border: 1px solid;
}

.alert-success {
  background: var(--success-bg);
  color: var(--success-text);
  border-color: var(--success-border);
}

Colorblind-Friendly Design

Tips for accessible color choices:

/* Avoid red/green alone for status */
.wrong {
  color: #dc2626; /* Red */
  /* Add icon for colorblind users */
}

.correct {
  color: #16a34a; /* Green */
  /* Add checkmark icon */
}

/* Better: Use both color AND icons */
.status {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.status::before {
  content: '';
  width: 8px;
  height: 8px;
  border-radius: 50%;
}

.status-success::before { background: #16a34a; }
.status-error::before { background: #dc2626; }

Tools for Color

Color Pickers

Color Functions in CSS

/* Color manipulation */
.hero {
  /* Overlay with color */
  background: linear-gradient(
    to right,
    rgba(37, 99, 235, 0.9),
    rgba(37, 99, 235, 0.7)
  );
}

/* Blend modes */
.icon {
  mix-blend-mode: multiply;
  background: white;
}

Summary

Key color implementation principles:

  • Use HSL for easier color manipulation
  • Follow 60-30-10 for balanced palettes
  • Ensure WCAG contrast for accessibility
  • Use CSS custom properties for maintainability
  • Support dark mode with prefers-color-scheme
  • Add icons for colorblind accessibility
  • Test on real devices for accurate colors

Good color choices can make your design memorable and accessible!

Comments