csscolorsdesign

HEX vs RGB vs HSL: Understanding CSS Color Formats

· Cosyslabs

HEX is the most compact notation for fixed colors in CSS. RGB is best when you need individual channel control or opacity. HSL is superior for programmatic color manipulation like rotating hue or adjusting lightness. OKLCH provides perceptually uniform interpolation and is now the recommended format for design tokens in modern CSS.

HEX Colors

Hexadecimal colors encode RGB values as a six-digit (or three-digit shorthand) hex number:

color: #FF5733;   /* R=255, G=87, B=51 */
color: #F53;      /* Shorthand — expands to #FF5533 */
color: #FF573380; /* With alpha — last two digits */

The format is #RRGGBB where each pair ranges from 00 (0) to FF (255).

HEX strengths:

  • Most compact notation
  • Universally supported (CSS Level 1)
  • Familiar to designers and developers
  • Easy to copy from design tools like Figma

HEX weaknesses:

  • Hard to reason about — what does #7B3F9E look like?
  • Difficult to modify programmatically — you must decode, modify channel, re-encode
  • Alpha support (#RRGGBBAA) only in CSS Colors Level 4 (not IE11)

RGB Colors

RGB specifies red, green, and blue channels as integers 0–255 or percentages:

color: rgb(255, 87, 51);
color: rgb(100% 34% 20%);     /* Modern space-separated syntax */
color: rgba(255, 87, 51, 0.5); /* With 50% opacity */
color: rgb(255 87 51 / 0.5);   /* Modern syntax with alpha */

RGB strengths:

  • Direct channel control — useful for image processing or canvas
  • rgba() for opacity (widely supported)
  • Easy to interpolate for animations

RGB weaknesses:

  • Counterintuitive for creating color palettes
  • No clear relationship between channel values and perceived color
  • Hard to create harmonious variations (complementary, analogous, triadic)

HSL Colors

HSL separates hue (color wheel position), saturation (color intensity), and lightness (brightness):

color: hsl(11, 100%, 60%);       /* Hue=11°, Sat=100%, Light=60% */
color: hsl(11deg 100% 60%);      /* Modern syntax */
color: hsl(11 100% 60% / 0.5);   /* With alpha */
  • Hue: 0–360 degrees on the color wheel. 0°/360°=red, 120°=green, 240°=blue
  • Saturation: 0%=gray, 100%=full color
  • Lightness: 0%=black, 50%=normal, 100%=white

HSL strengths:

  • Intuitive — you can visualize a color from its values
  • Easy to create color variations programmatically:
// Generate 5-step tint/shade palette from a base hue
function generatePalette(hue) {
  return [
    `hsl(${hue} 80% 90%)`,  // lightest
    `hsl(${hue} 70% 70%)`,
    `hsl(${hue} 65% 50%)`,  // base
    `hsl(${hue} 70% 35%)`,
    `hsl(${hue} 75% 20%)`,  // darkest
  ];
}

// Complementary color (180° opposite)
function complement(hue) {
  return `hsl(${(hue + 180) % 360} 65% 50%)`;
}

// Analogous colors (30° apart)
function analogous(hue) {
  return [
    `hsl(${(hue - 30 + 360) % 360} 65% 50%)`,
    `hsl(${hue} 65% 50%)`,
    `hsl(${(hue + 30) % 360} 65% 50%)`,
  ];
}

HSL weaknesses:

  • Not perceptually uniform — two colors with the same lightness may appear very different in perceived brightness
  • Yellow at 50% lightness appears much brighter than blue at 50% lightness

OKLCH: The Modern Standard

OKLCH (Oklab Lightness-Chroma-Hue) is a perceptually uniform color space now supported in all modern browsers:

color: oklch(0.65 0.2 30);       /* L=65%, C=0.2, H=30° */
color: oklch(65% 0.2 30deg);
color: oklch(0.65 0.2 30 / 0.5); /* With alpha */
  • L (Lightness): 0=black, 1=white — perceptually uniform
  • C (Chroma): color intensity, 0=gray, max varies by hue
  • H (Hue): 0–360 degrees

Why OKLCH is better for design tokens:

/* HSL — same lightness, but yellow looks much brighter than blue */
:root {
  --yellow: hsl(60 100% 50%);  /* Very bright-looking */
  --blue:   hsl(240 100% 50%); /* Looks much darker */
}

/* OKLCH — perceptually uniform lightness */
:root {
  --yellow: oklch(0.87 0.17 102); /* Both appear equally bright */
  --blue:   oklch(0.45 0.21 264);
}

OKLCH excels at:

  • Generating accessible color palettes with predictable contrast ratios
  • Smooth color gradients without muddy intermediate colors
  • Design tokens that maintain visual balance across hues
/* OKLCH gradient stays vibrant — no gray middle */
.gradient {
  background: linear-gradient(
    in oklch,
    oklch(0.6 0.2 30),
    oklch(0.6 0.2 270)
  );
}

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

// 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;
  const 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) };
}

WCAG Contrast Requirements

Choosing colors is not just about aesthetics — accessibility requires minimum contrast ratios between text and background:

LevelNormal TextLarge Text (18pt/14pt bold)
AA (minimum)4.5:13:1
AAA (enhanced)7:14.5:1

Use the Color Contrast Checker Tool to verify WCAG compliance for any color pair.

Which Format to Use

SituationFormat
Copying from Figma/SketchHEX
Static brand colorsHEX or RGB
Opacity/transparencyrgb() with alpha, or oklch()
Programmatic palette generationHSL or OKLCH
Design system tokensOKLCH
CSS gradientsoklch in color-interpolation-method
Legacy browser supportHEX or rgba()

Try It Now

Convert between HEX, RGB, HSL, and OKLCH with the Color Picker & Converter — see live previews and accessibility contrast scores for any color.

More Tools from Cosyslabs

  • PDF Convert All — PDF documents use CMYK color internally — when exporting design work to PDF, understanding how RGB maps to CMYK prevents color shift surprises.
  • Rough Estimator — Estimate the design and implementation effort for building a brand color system or migrating a design system from HEX to OKLCH tokens.
  • Routine Toolkit — Everyday productivity tools from the same team, including a word counter, date calculator, and loan amortization calculator.
  • Cosyslabs — The studio behind Dev Tools !, Unit Convert All, Astrilio, CastFleet, and more.