Color Models for Web Development

Different color models describe the same colors in different ways. Understanding when to use each makes your work faster and your code more maintainable.

RGB (Red, Green, Blue)

The foundation of digital color. Every color is a mix of red, green, and blue light.

Syntax

/* Functional notation */
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 */

/* With alpha (transparency) */
color: rgba(255, 0, 0, 0.5);  /* 50% transparent red */
color: rgb(255 0 0 / 50%);    /* Modern syntax */

How It Works

Each channel ranges from 0-255 (8-bit = 256 values per channel).

Red:   0 ──────────────────── 255
Green: 0 ──────────────────── 255  → 16.7 million possible colors
Blue:  0 ──────────────────── 255

Common RGB Values

ColorRGB
Blackrgb(0, 0, 0)
Whitergb(255, 255, 255)
Redrgb(255, 0, 0)
Greenrgb(0, 255, 0)
Bluergb(0, 0, 255)
Yellowrgb(255, 255, 0)
Cyanrgb(0, 255, 255)
Magentargb(255, 0, 255)
Grayrgb(128, 128, 128)

When to Use RGB

  • When working with code that outputs RGB
  • When you need precise control over individual channels
  • For programmatic color manipulation

Drawbacks

RGB is not intuitive. Quick: what's rgb(147, 112, 219)? Hard to visualize. (It's a medium purple.)

HEX (Hexadecimal)

HEX is RGB written in base-16. Same colors, different notation.

Syntax

color: #FF0000;    /* Red */
color: #00FF00;    /* Green */
color: #0000FF;    /* Blue */
color: #FFFFFF;    /* White */
color: #000000;    /* Black */

/* Shorthand (when each pair is identical) */
color: #F00;       /* Same as #FF0000 */
color: #0F0;       /* Same as #00FF00 */
color: #FFF;       /* Same as #FFFFFF */

/* With alpha (8-digit hex) */
color: #FF000080;  /* 50% transparent red */

Reading HEX Values

#FF5733
 ││││││
 ││││└┴── Blue:  0x33 = 51
 ││└┴──── Green: 0x57 = 87
 └┴────── Red:   0xFF = 255

Hexadecimal digits: 0 1 2 3 4 5 6 7 8 9 A B C D E F

Quick conversions:

  • 00 = 0
  • 80 = 128 (halfway)
  • FF = 255

When to Use HEX

  • Most common format in design tools and codebases
  • Compact representation
  • Easy to copy/paste from design tools
  • Good for color constants/variables

Drawbacks

Same problem as RGB - not intuitive for manipulation. What color is 20% lighter than #3498db? You can't easily calculate it.

HSL (Hue, Saturation, Lightness)

The most intuitive model for designers and developers. Maps directly to how we think about color.

Syntax

color: hsl(0, 100%, 50%);      /* Red */
color: hsl(120, 100%, 50%);    /* Green */
color: hsl(240, 100%, 50%);    /* Blue */

/* With alpha */
color: hsla(0, 100%, 50%, 0.5);  /* 50% transparent red */
color: hsl(0 100% 50% / 50%);    /* Modern syntax */

The Three Components

Hue (0-360): Position on the color wheel

0°/360° = Red
60°     = Yellow
120°    = Green
180°    = Cyan
240°    = Blue
300°    = Magenta

Saturation (0-100%): Intensity of the color

0%   = Gray (no color)
50%  = Muted
100% = Vivid, pure color

Lightness (0-100%): Light to dark

0%   = Black
50%  = Pure hue
100% = White

Visual Representation

Saturation →
100% ┌────────────────────┐
     │ Vivid              │
     │                    │
 50% │ Muted              │  ↑
     │                    │  Lightness
  0% │ Gray───────────────│
     └────────────────────┘
      0%      50%      100%

Creating Color Variations with HSL

This is where HSL shines:

:root {
  /* Base color */
  --primary: hsl(220, 90%, 50%);

  /* Lighter version - just increase lightness */
  --primary-light: hsl(220, 90%, 70%);

  /* Darker version - just decrease lightness */
  --primary-dark: hsl(220, 90%, 30%);

  /* Muted version - decrease saturation */
  --primary-muted: hsl(220, 40%, 50%);

  /* Hover state - slightly different lightness */
  --primary-hover: hsl(220, 90%, 45%);
}

When to Use HSL

  • Color manipulation - Creating tints, shades, hover states
  • Building color scales - Systematic lightness/saturation steps
  • Design systems - Consistent color relationships
  • Dark mode - Easy to adjust lightness values
  • Accessibility - Quick contrast adjustments

HSL is Best for CSS Custom Properties

:root {
  --hue-primary: 220;
  --hue-success: 142;
  --hue-warning: 38;
  --hue-error: 0;
}

.button-primary {
  background: hsl(var(--hue-primary), 90%, 50%);
}

.button-primary:hover {
  background: hsl(var(--hue-primary), 90%, 45%);
}

.text-primary-light {
  color: hsl(var(--hue-primary), 70%, 70%);
}

HSB/HSV (Hue, Saturation, Brightness/Value)

Used by design tools (Photoshop, Figma) but not directly supported in CSS.

How It Differs from HSL

HSL Lightness:           HSB Brightness:
100% = White             100% = Full color
50%  = Full color        50%  = Darker
0%   = Black             0%   = Black

In HSB:

  • Brightness 100% + Saturation 100% = vivid color
  • Brightness 100% + Saturation 0% = white

If your design tool uses HSB, you'll need to convert to HSL or RGB for CSS.

Comparison Table

ModelFormatIntuitive?CSS SupportBest For
RGBrgb(255, 128, 0)NoYesProgrammatic manipulation
HEX#FF8000NoYesConstants, copy/paste
HSLhsl(30, 100%, 50%)YesYesDesign work, variations
HSBhsb(30, 100%, 100%)YesNoDesign tools only

Converting Between Models

In JavaScript

// HEX to RGB
function hexToRgb(hex) {
  const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
  return result ? {
    r: parseInt(result[1], 16),
    g: parseInt(result[2], 16),
    b: parseInt(result[3], 16)
  } : null;
}

// RGB to HSL
function rgbToHsl(r, g, b) {
  r /= 255; g /= 255; b /= 255;
  const max = Math.max(r, g, b), min = Math.min(r, g, b);
  let h, s, l = (max + min) / 2;

  if (max === min) {
    h = s = 0;
  } else {
    const d = max - min;
    s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
    switch (max) {
      case r: h = ((g - b) / d + (g < b ? 6 : 0)) / 6; break;
      case g: h = ((b - r) / d + 2) / 6; break;
      case b: h = ((r - g) / d + 4) / 6; break;
    }
  }
  return { h: h * 360, s: s * 100, l: l * 100 };
}

In Browser DevTools

Most browser DevTools let you click on a color value and cycle through formats (Shift+Click on the color swatch in Chrome/Firefox).

Modern CSS: OKLCH and LCH

Newer color spaces that are more perceptually uniform (equal steps in values = equal perceived differences).

/* LCH: Lightness, Chroma, Hue */
color: lch(50% 100 270);

/* OKLCH: Improved version */
color: oklch(60% 0.15 250);

These are gaining browser support and are better for:

  • Creating perceptually even color scales
  • Maintaining consistent perceived contrast
  • Wider color gamut displays

For now, HSL handles most needs, but watch OKLCH for the future.

Practical Recommendations

  1. Store colors as HEX in your design tokens/constants
  2. Use HSL for CSS when you need variations
  3. Use RGB for JavaScript color manipulation
  4. Use CSS custom properties with HSL for theming
:root {
  /* Define base colors */
  --color-primary-h: 220;
  --color-primary-s: 90%;
  --color-primary-l: 50%;

  /* Compose full color */
  --color-primary: hsl(
    var(--color-primary-h),
    var(--color-primary-s),
    var(--color-primary-l)
  );

  /* Easy variations */
  --color-primary-light: hsl(
    var(--color-primary-h),
    var(--color-primary-s),
    70%
  );
}

Summary

ModelRemember
RGB0-255 for each channel, foundation of digital color
HEXRGB in base-16, most common format
HSLHue (0-360), Saturation (0-100%), Lightness (0-100%) - use this
HSBDesign tools use this, convert to HSL for CSS

Next: 03-color-wheel.md - Understanding color relationships