Web Colors: HEX, RGB, HSL Explained Simply

THEJORD Team1 min read
colorscssdesignwebtools

Understand color formats: HEX, RGB, HSL, RGBA. When to use which and how to convert.

Web Colors: HEX, RGB, HSL Explained Simply

Introduction to Web Colors

Colors are fundamental to web design, and understanding different color formats is essential for every developer. Whether you're working with CSS, designing interfaces, or ensuring accessibility, knowing how HEX, RGB, and HSL work helps you make better decisions. This guide explains each format, when to use them, and how to convert between them.

HEX Colors

Understanding HEX Format

HEX (hexadecimal) is the most common color format in web development. It represents colors as six-digit codes preceded by a hash symbol:

#RRGGBB

Examples:
#FF0000 → Red
#00FF00 → Green
#0000FF → Blue
#FFFFFF → White
#000000 → Black
#808080 → Gray

How HEX Works

Each pair of digits represents a color channel (0-255 in decimal, 00-FF in hex):

  • First pair (RR): Red intensity (00-FF)
  • Second pair (GG): Green intensity (00-FF)
  • Third pair (BB): Blue intensity (00-FF)
#3498DB breakdown:
34 → Red = 52 (decimal)
98 → Green = 152 (decimal)
DB → Blue = 219 (decimal)

Shorthand HEX

When each pair has identical digits, use the 3-digit shorthand:

#FF0000 → #F00
#00FF00 → #0F0
#336699 → #369
#AABBCC → #ABC

HEX with Alpha

Modern browsers support 8-digit HEX for transparency:

#RRGGBBAA

#FF000080 → Red at 50% opacity
#3498DBCC → Blue at 80% opacity

// Or 4-digit shorthand
#F008 → Red at 50% opacity

RGB Colors

Understanding RGB Format

RGB directly specifies red, green, and blue values from 0 to 255:

rgb(red, green, blue)

Examples:
rgb(255, 0, 0)    → Red
rgb(0, 255, 0)    → Green
rgb(0, 0, 255)    → Blue
rgb(255, 255, 255) → White
rgb(0, 0, 0)      → Black

RGBA for Transparency

Add an alpha channel (0 to 1) for transparency:

rgba(red, green, blue, alpha)

rgba(255, 0, 0, 0.5)   → 50% transparent red
rgba(0, 0, 0, 0.8)     → 80% opaque black
rgba(255, 255, 255, 0) → Fully transparent

Modern RGB Syntax

CSS Color Level 4 allows a cleaner syntax:

// Space-separated values
rgb(255 0 0)
rgb(255 0 0 / 50%)      → With alpha as percentage
rgb(255 0 0 / 0.5)      → With alpha as decimal

// Percentage values
rgb(100% 0% 0%)         → Same as rgb(255 0 0)

HSL Colors

Understanding HSL Format

HSL (Hue, Saturation, Lightness) is more intuitive for color manipulation:

hsl(hue, saturation, lightness)

hue:        0-360 degrees on color wheel
saturation: 0-100% (gray to full color)
lightness:  0-100% (black to white)

The Color Wheel

Hue degrees:
0°   / 360° → Red
60°         → Yellow
120°        → Green
180°        → Cyan
240°        → Blue
300°        → Magenta

HSL Examples

hsl(0, 100%, 50%)   → Pure red
hsl(120, 100%, 50%) → Pure green
hsl(240, 100%, 50%) → Pure blue

hsl(0, 100%, 25%)   → Dark red
hsl(0, 100%, 75%)   → Light red
hsl(0, 50%, 50%)    → Muted red
hsl(0, 0%, 50%)     → Gray (no saturation)

HSLA for Transparency

hsla(hue, saturation, lightness, alpha)

hsla(0, 100%, 50%, 0.5)  → 50% transparent red
hsla(240, 100%, 50%, 0.8) → 80% opaque blue

Comparing Formats

AspectHEXRGBHSL
ReadabilityCompactClear valuesIntuitive
ManipulationDifficultModerateEasy
Browser supportUniversalUniversalUniversal
Common useBrand colorsDynamic colorsTheme systems
Transparency8-digitrgba()hsla()

When to Use Each Format

Use HEX When

  • Working with brand colors from design specs
  • You need compact color codes
  • Colors won't need manipulation
  • Copying colors from design tools

Use RGB When

  • Calculating colors programmatically
  • Working with image data (canvas, pixel manipulation)
  • Need to adjust individual color channels
  • Working with color libraries

Use HSL When

  • Creating color themes and variations
  • Adjusting color brightness or saturation
  • Building accessible color palettes
  • Creating hover/active states

Color Manipulation with HSL

Creating Color Variations

// Base color
--primary: hsl(220, 80%, 50%);

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

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

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

// Hover state (slight lightness change)
--primary-hover: hsl(220, 80%, 45%);

Creating a Color Scale

:root {
  --blue-50:  hsl(220, 80%, 95%);
  --blue-100: hsl(220, 80%, 90%);
  --blue-200: hsl(220, 80%, 80%);
  --blue-300: hsl(220, 80%, 70%);
  --blue-400: hsl(220, 80%, 60%);
  --blue-500: hsl(220, 80%, 50%);  /* Base */
  --blue-600: hsl(220, 80%, 40%);
  --blue-700: hsl(220, 80%, 30%);
  --blue-800: hsl(220, 80%, 20%);
  --blue-900: hsl(220, 80%, 10%);
}

CSS Color Functions

Modern CSS Color-Mix

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

/* Create tints and shades */
color: color-mix(in srgb, blue, white 20%);  /* Lighter blue */
color: color-mix(in srgb, blue, black 20%);  /* Darker blue */

Relative Colors (CSS Color Level 5)

/* Adjust existing colors */
--base: hsl(220, 80%, 50%);

/* Make it 20% lighter */
--lighter: hsl(from var(--base) h s calc(l + 20%));

/* Rotate hue by 30 degrees */
--shifted: hsl(from var(--base) calc(h + 30) s l);

Color Conversion

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;
}

hexToRgb("#3498DB"); // { r: 52, g: 152, b: 219 }

RGB to HEX

function rgbToHex(r, g, b) {
  return "#" + [r, g, b]
    .map(x => x.toString(16).padStart(2, '0'))
    .join('');
}

rgbToHex(52, 152, 219); // "#3498db"

RGB to HSL

function rgbToHsl(r, g, b) {
  r /= 255; g /= 255; b /= 255;
  const max = Math.max(r, g, b);
  const 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: Math.round(h * 360),
    s: Math.round(s * 100),
    l: Math.round(l * 100)
  };
}

Color Accessibility

Contrast Ratios

WCAG requires minimum contrast ratios:

  • Normal text: 4.5:1 (AA) or 7:1 (AAA)
  • Large text: 3:1 (AA) or 4.5:1 (AAA)
  • UI components: 3:1
// Calculate relative luminance
function luminance(r, g, b) {
  const [rs, gs, bs] = [r, g, b].map(c => {
    c /= 255;
    return c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
  });
  return 0.2126 * rs + 0.7152 * gs + 0.0722 * bs;
}

// Calculate contrast ratio
function contrastRatio(rgb1, rgb2) {
  const l1 = luminance(...rgb1);
  const l2 = luminance(...rgb2);
  const lighter = Math.max(l1, l2);
  const darker = Math.min(l1, l2);
  return (lighter + 0.05) / (darker + 0.05);
}

Creating Accessible Palettes

// Ensure text is readable on background
function getAccessibleTextColor(bgColor) {
  const rgb = hexToRgb(bgColor);
  const lum = luminance(rgb.r, rgb.g, rgb.b);
  return lum > 0.179 ? '#000000' : '#FFFFFF';
}

Tools and Resources

For working with colors:

CSS Named Colors

CSS provides 147 named colors for convenience:

/* Common named colors */
color: red;        /* #FF0000 */
color: blue;       /* #0000FF */
color: green;      /* #008000 (not #00FF00!) */
color: lime;       /* #00FF00 */
color: navy;       /* #000080 */
color: teal;       /* #008080 */
color: coral;      /* #FF7F50 */
color: salmon;     /* #FA8072 */
color: rebeccapurple; /* #663399 */

Best Practices

  • Use CSS custom properties: Define colors once, use everywhere
  • Choose HSL for themes: Easier to create consistent variations
  • Test contrast: Always verify text readability
  • Document color choices: Include semantic names (--color-error, not --red)
  • Consider color blindness: Don't rely on color alone for meaning

Conclusion

Understanding color formats helps you write better CSS and create more accessible designs. Key takeaways:

  • HEX is compact and universal but hard to manipulate
  • RGB is clear and works well with calculations
  • HSL is intuitive and perfect for creating color systems
  • Always check contrast ratios for accessibility
  • Use CSS custom properties for maintainable color systems

For more developer resources, explore our free online tools. For detailed specifications, see MDN CSS Color Values and WCAG Contrast Guidelines.