Color picking is not just selecting a hex string. A picker exposes a representation of a color; the displayed result also depends on the source profile, transfer function, alpha compositing, display, and user settings. This guide separates notation from appearance and shows how to build a palette that can be tested in a real interface.

Table of Contents

Key Takeaways

  • RGB is Additive: Red, green, blue light combine to produce colors, used for screen display
  • HSL is an authoring control: Hue, saturation, and lightness can be convenient, but HSL is not perceptually uniform
  • HEX is RGB Shorthand: Hexadecimal format is a compact representation of RGB values
  • Transparency Support: RGBA and HSLA support alpha channel for semi-transparent effects
  • CSS Variables: Use CSS custom properties to manage colors for easy theme switching

Color Models Explained

RGB Model

RGB (Red, Green, Blue) is an additive color model that produces colors by combining different intensities of red, green, and blue light.

Characteristics:

  • Each channel value range: 0-255
  • Total colors: 256³ = 16,777,216
  • Used for screen display (light-emitting devices)

Color Mixing Examples:

Color R G B
Red 255 0 0
Green 0 255 0
Blue 0 0 255
Yellow 255 255 0
Cyan 0 255 255
Magenta 255 0 255
White 255 255 255
Black 0 0 0

HSL Model

HSL (Hue, Saturation, Lightness) is a convenient cylindrical representation for authoring, not a perceptual scale. Equal changes in L do not produce equal perceived lightness across hues.

Parameters:

  • Hue: 0-360 degrees, position on the color wheel
    • 0°/360°: Red
    • 120°: Green
    • 240°: Blue
  • Saturation: 0%-100%, color vividness
    • 0%: Gray
    • 100%: Pure color
  • Lightness: 0%-100%, brightness level
    • 0%: Black
    • 50%: Pure color
    • 100%: White

HSV/HSB Model

HSV (Hue, Saturation, Value), also called HSB (Brightness), is similar to HSL but with different brightness definition.

Web Color Formats

HEX Format

In CSS, hexadecimal notation represents sRGB channels. It may contain 3, 4, 6, or 8 hex digits; the 4/8-digit forms include alpha.

css
/* 6-digit format */
color: #FF5733;
color: #ffffff;

/* 3-digit shorthand */
color: #F53;  /* equals #FF5533 */
color: #fff;  /* equals #ffffff */

/* 8-digit format (with alpha) */
color: #FF573380;  /* last two digits are alpha */

RGB/RGBA Format

css
/* RGB format */
color: rgb(255, 87, 51);

/* RGBA format (with alpha) */
color: rgba(255, 87, 51, 0.5);

/* Modern CSS syntax */
color: rgb(255 87 51);
color: rgb(255 87 51 / 50%);

HSL/HSLA Format

css
/* HSL format */
color: hsl(11, 100%, 60%);

/* HSLA format (with alpha) */
color: hsla(11, 100%, 60%, 0.5);

/* Modern CSS syntax */
color: hsl(11 100% 60% / 50%);

Color Keywords

CSS defines a finite set of named color keywords:

css
color: red;
color: blue;
color: transparent;
color: currentColor;

Color Format Conversion

HEX to RGB

javascript
function hexToRgb(hex) {
  const value = String(hex).replace(/^#/, '');
  const expanded = value.length === 3 || value.length === 4
    ? [...value].map(char => char + char).join('')
    : value;
  if (!/^[\da-f]{6}([\da-f]{2})?$/i.test(expanded)) {
    throw new RangeError('expected #RGB, #RGBA, #RRGGBB, or #RRGGBBAA');
  }
  return {
    r: parseInt(expanded.slice(0, 2), 16),
    g: parseInt(expanded.slice(2, 4), 16),
    b: parseInt(expanded.slice(4, 6), 16),
    ...(expanded.length === 8
      ? { a: parseInt(expanded.slice(6, 8), 16) / 255 }
      : { a: 1 })
  };
}

hexToRgb('#FF5733'); // { r: 255, g: 87, b: 51 }

RGB to HEX

javascript
function rgbToHex(r, g, b) {
  const channels = [r, g, b];
  if (!channels.every(Number.isInteger) ||
      channels.some(channel => channel < 0 || channel > 255)) {
    throw new RangeError('RGB channels must be integers from 0 to 255');
  }
  return '#' + [r, g, b].map(x => {
    const hex = x.toString(16);
    return hex.length === 1 ? '0' + hex : hex;
  }).join('');
}

rgbToHex(255, 87, 51); // '#ff5733'

Code Examples

CSS Variables for Color Management

css
:root {
  --color-primary: #3498db;
  --color-primary-light: #5dade2;
  --color-primary-dark: #2980b9;
  
  --color-success: #27ae60;
  --color-warning: #f39c12;
  --color-error: #e74c3c;
}

.button-primary {
  background-color: var(--color-primary);
}

/* Dark theme */
[data-theme="dark"] {
  --color-text: #ffffff;
  --color-background: #1a1a1a;
}

JavaScript Color Class

javascript
class Color {
  constructor(r, g, b, a = 1) {
    this.r = r;
    this.g = g;
    this.b = b;
    this.a = a;
  }

  static fromHex(hex) {
    const value = hexToRgb(hex);
    return new Color(value.r, value.g, value.b, value.a);
  }

  toHex() {
    const toHex = n => n.toString(16).padStart(2, '0');
    return `#${toHex(this.r)}${toHex(this.g)}${toHex(this.b)}`;
  }

  lighten(percent) {
    if (!Number.isFinite(percent) || percent < 0 || percent > 100) {
      throw new RangeError('percent must be between 0 and 100');
    }
    // Channel arithmetic is illustrative; use a perceptual space for production palettes.
    const amount = Math.round(255 * percent / 100);
    return new Color(
      Math.min(255, this.r + amount),
      Math.min(255, this.g + amount),
      Math.min(255, this.b + amount)
    );
  }
}

Best Practices

1. Use Semantic Color Names

css
/* Recommended */
--color-primary: #3498db;
--color-success: #27ae60;

/* Not recommended */
--blue: #3498db;
--green: #27ae60;

2. Build a Color System

css
--color-primary-50: #e3f2fd;
--color-primary-100: #bbdefb;
--color-primary-500: #2196f3;  /* Base color */
--color-primary-900: #0d47a1;

3. Ensure Contrast Ratio

For WCAG 2.x AA, normal text generally needs at least 4.5:1 and large text 3:1. Large text is defined by rendered point size and weight, not a universal CSS pixel value. Test focus indicators, non-text graphics, disabled states, and alpha-composited colors too.

4. Support Dark Mode

css
@media (prefers-color-scheme: dark) {
  :root {
    --color-text: #ffffff;
    --color-background: #121212;
  }
}

Frequently Asked Questions

What's the difference between HEX and RGB?

HEX is a hexadecimal notation for RGB channel values, not a new color model. HEX is compact, while RGB makes channels and alpha more explicit.

When should I use HSL?

When you need to adjust color brightness or saturation, HSL is more convenient. For example, creating different shades of the same hue.

How do I choose appropriate color contrast?

Use the intended sRGB foreground and the actual composited background, then verify the rendered component. WCAG ratios do not replace testing focus visibility, state changes, images, gradients, or user-selected themes.

Does a color picker show the “true” color?

Not necessarily. Appearance depends on color profiles, display gamut, brightness, ambient light, browser behavior, and alpha compositing. Preserve profile metadata for images and treat a picker value as a representation with stated assumptions.

Conclusion

Understanding models and web color formats helps teams create maintainable palettes, but a hex value alone does not guarantee appearance or accessibility. Use semantic tokens, test real states, and document the color space and contrast assumptions.

Quick Summary:

  • RGB for screen-oriented channel values; HSL is a convenient authoring representation, not a perceptual guarantee
  • HEX is compact RGB representation, most common in web development
  • Use CSS variables to manage colors for easy theme switching
  • Ensure text and background contrast meets accessibility standards
  • Build systematic color schemes with primary, secondary, and semantic colors

Further Reading