How to Convert Colors (HEX to RGB to HSL)

Learn how to convert colors between HEX, RGB, and HSL formats in JavaScript. Complete tutorial with code examples and color conversion utilities.

How to Convert Colors (HEX to RGB to HSL)

Working with colors in web development means converting between different formats. HEX is great for CSS, RGB is useful for manipulation, and HSL is intuitive for adjustments. This tutorial shows you how to convert between all major color formats in JavaScript.

Color Formats Explained

| Format | Example | Use Case | |--------|---------|----------| | HEX | #3B82F6 | CSS, design tools | | RGB | rgb(59, 130, 246) | Programmatic manipulation | | RGBA | rgba(59, 130, 246, 0.5) | With transparency | | HSL | hsl(217, 91%, 60%) | Intuitive adjustments | | HSLA | hsla(217, 91%, 60%, 0.5) | HSL with transparency |

HEX to RGB Conversion

function hexToRgb(hex) {
  // Remove the # if present
  hex = hex.replace(/^#/, '');

// Parse hex values const r = parseInt(hex.slice(0, 2), 16); const g = parseInt(hex.slice(2, 4), 16); const b = parseInt(hex.slice(4, 6), 16);

return { r, g, b }; }

// Usage const rgb = hexToRgb('#3B82F6'); console.log(rgb); // { r: 59, g: 130, b: 246 }

// Or as CSS string function hexToRgbString(hex) { const { r, g, b } = hexToRgb(hex); return rgb(${r}, ${g}, ${b}); }

console.log(hexToRgbString('#3B82F6')); // "rgb(59, 130, 246)"

Handling Short HEX (3-digit)

function hexToRgb(hex) {
  hex = hex.replace(/^#/, '');

// Expand 3-digit hex to 6-digit if (hex.length === 3) { hex = hex.split('').map(c => c + c).join(''); }

const r = parseInt(hex.slice(0, 2), 16); const g = parseInt(hex.slice(2, 4), 16); const b = parseInt(hex.slice(4, 6), 16);

return { r, g, b }; }

// Usage hexToRgb('#3BF'); // Same as #33BBFF // { r: 51, g: 187, b: 255 }

RGB to HEX Conversion

function componentToHex(c) {
  // Clamp value between 0 and 255
  const clamped = Math.max(0, Math.min(255, c));
  const hex = clamped.toString(16);
  return hex.length === 1 ? '0' + hex : hex;
}

function rgbToHex(r, g, b) { return '#' + componentToHex(r) + componentToHex(g) + componentToHex(b); }

// Usage const hex = rgbToHex(59, 130, 246); console.log(hex); // "#3b82f6"

RGB to HSL Conversion

function rgbToHsl(r, g, b) {
  // Normalize to 0-1 range
  r /= 255;
  g /= 255;
  b /= 255;

const max = Math.max(r, g, b); const min = Math.min(r, g, b); let h, s; const l = (max + min) / 2;

if (max === min) { // Achromatic (gray) 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; } }

// Convert to degrees and percentages return { h: Math.round(h 360), s: Math.round(s 100), l: Math.round(l 100) }; }

// Usage const hsl = rgbToHsl(59, 130, 246); console.log(hsl); // { h: 217, s: 91, l: 60 }

// As CSS string function rgbToHslString(r, g, b) { const { h, s, l } = rgbToHsl(r, g, b); return hsl(${h}, ${s}%, ${l}%); }

console.log(rgbToHslString(59, 130, 246)); // "hsl(217, 91%, 60%)"

HSL to RGB Conversion

function hueToRgb(p, q, t) {
  if (t < 0) t += 1;
  if (t > 1) t -= 1;
  if (t < 1/6) return p + (q - p)  6  t;
  if (t < 1/2) return q;
  if (t < 2/3) return p + (q - p)  (2/3 - t)  6;
  return p;
}

function hslToRgb(h, s, l) { // Normalize to 0-1 range h /= 360; s /= 100; l /= 100;

let r, g, b;

if (s === 0) { // Achromatic r = g = b = l; } else { const q = l < 0.5 ? l (1 + s) : l + s - l s; const p = 2 l - q;

r = hueToRgb(p, q, h + 1/3); g = hueToRgb(p, q, h); b = hueToRgb(p, q, h - 1/3); }

return { r: Math.round(r 255), g: Math.round(g 255), b: Math.round(b 255) }; }

// Usage const rgb = hslToRgb(217, 91, 60); console.log(rgb); // { r: 59, g: 130, b: 246 }

HEX to HSL and HSL to HEX

function hexToHsl(hex) {
  const { r, g, b } = hexToRgb(hex);
  return rgbToHsl(r, g, b);
}

function hslToHex(h, s, l) { const { r, g, b } = hslToRgb(h, s, l); return rgbToHex(r, g, b); }

// Usage hexToHsl('#3B82F6'); // { h: 217, s: 91, l: 60 }

hslToHex(217, 91, 60); // "#3b82f6"

Complete Color Converter Class

class ColorConverter {
  // Parse any color format to RGB
  static parse(color) {
    if (typeof color !== 'string') return null;
    color = color.trim().toLowerCase();

// HEX: #3B82F6 or #3BF if (color.startsWith('#')) { return this.hexToRgb(color); }

// RGB/RGBA: rgb(59, 130, 246) or rgba(59, 130, 246, 0.5) const rgbMatch = color.match(/rgba?\((\d+),\s(\d+),\s(\d+)(?:,\s([\d.]+))?\)/); if (rgbMatch) { return { r: parseInt(rgbMatch[1]), g: parseInt(rgbMatch[2]), b: parseInt(rgbMatch[3]), a: rgbMatch[4] !== undefined ? parseFloat(rgbMatch[4]) : 1 }; }

// HSL/HSLA: hsl(217, 91%, 60%) or hsla(217, 91%, 60%, 0.5) const hslMatch = color.match(/hsla?\((\d+),\s(\d+)%,\s(\d+)(?:%,\s([\d.]+))?\)/); if (hslMatch) { const h = parseInt(hslMatch[1]); const s = parseInt(hslMatch[2]); const l = parseInt(hslMatch[3]); const a = hslMatch[4] !== undefined ? parseFloat(hslMatch[4]) : 1; return { ...this.hslToRgb(h, s, l), a }; }

return null; }

static hexToRgb(hex) { hex = hex.replace(/^#/, ''); if (hex.length === 3) { hex = hex.split('').map(c => c + c).join(''); } return { r: parseInt(hex.slice(0, 2), 16), g: parseInt(hex.slice(2, 4), 16), b: parseInt(hex.slice(4, 6), 16), a: 1 }; }

static rgbToHex(r, g, b) { const toHex = c => { const clamped = Math.max(0, Math.min(255, c)); const hex = clamped.toString(16); return hex.length === 1 ? '0' + hex : hex; }; return '#' + toHex(r) + toHex(g) + toHex(b); }

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

static hslToRgb(h, s, l) { h /= 360; s /= 100; l /= 100;

let r, g, b;

if (s === 0) { r = g = b = l; } else { const hueToRgb = (p, q, t) => { if (t < 0) t += 1; if (t > 1) t -= 1; if (t < 1/6) return p + (q - p) 6 t; if (t < 1/2) return q; if (t < 2/3) return p + (q - p) (2/3 - t) 6; return p; };

const q = l < 0.5 ? l (1 + s) : l + s - l s; const p = 2 l - q;

r = hueToRgb(p, q, h + 1/3); g = hueToRgb(p, q, h); b = hueToRgb(p, q, h - 1/3); }

return { r: Math.round(r 255), g: Math.round(g 255), b: Math.round(b 255) }; }

// Convert any color to any format static convert(color, format) { const rgb = this.parse(color); if (!rgb) return null;

switch (format) { case 'hex': return this.rgbToHex(rgb.r, rgb.g, rgb.b); case 'rgb': return rgb(${rgb.r}, ${rgb.g}, ${rgb.b}); case 'rgba': return rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${rgb.a}); case 'hsl': { const hsl = this.rgbToHsl(rgb.r, rgb.g, rgb.b); return hsl(${hsl.h}, ${hsl.s}%, ${hsl.l}%); } case 'hsla': { const hsl = this.rgbToHsl(rgb.r, rgb.g, rgb.b); return hsla(${hsl.h}, ${hsl.s}%, ${hsl.l}%, ${rgb.a}); } case 'object': return rgb; default: return null; } }

// Generate color variations static lighten(color, percent) { const rgb = this.parse(color); const hsl = this.rgbToHsl(rgb.r, rgb.g, rgb.b); hsl.l = Math.min(100, hsl.l + percent); return this.hslToHex(hsl.h, hsl.s, hsl.l); }

static darken(color, percent) { return this.lighten(color, -percent); }

static saturate(color, percent) { const rgb = this.parse(color); const hsl = this.rgbToHsl(rgb.r, rgb.g, rgb.b); hsl.s = Math.min(100, hsl.s + percent); return this.hslToHex(hsl.h, hsl.s, hsl.l); } }

// Usage ColorConverter.convert('#3B82F6', 'hsl'); // "hsl(217, 91%, 60%)"

ColorConverter.convert('hsl(217, 91%, 60%)', 'hex'); // "#3b82f6"

ColorConverter.lighten('#3B82F6', 10); // Lighter blue

ColorConverter.darken('#3B82F6', 10); // Darker blue

Try It Online

Need quick color conversions? Build a color converter tool or check out related developer tools at DevKits.

Conclusion

Converting between color formats is essential for dynamic theming, color pickers, and design tools. The ColorConverter class above handles all major formats and includes utilities for lightening, darkening, and saturating colors.

For more JavaScript utilities, see How to Minify CSS.

---

Related Tools:

🚀 Deploy Your Own Tools — Recommended Hosting

Want to self-host or build your own developer tools? These are the platforms we use:

🌐
Hostinger
Web Hosting from $2.99/mo
💧
DigitalOcean
$200 Free Credit for New Users
🔑
Namecheap
Domains from $0.99/yr

* Affiliate links — we may earn a commission at no extra cost to you.

😓 Tired of Online Tools That Don't Work Offline?

Get the complete offline toolkit. Perfect for flights, remote work, or privacy-focused development. No internet? No problem.

✈️

Offline Pack

82 tools, zero internet needed

🎒 Perfect for 100+ remote devs

$9 Get Offline →
📦

Content Pack

100 article templates ready

🎒 Perfect for 100+ remote devs

$19 Get Pack →
💰

Complete Bundle

All 3 products, save $18

🔥 Best value

$33 $15
Get All →

🔒 Works on flights, trains, remote cabins. Privacy-first, zero tracking.