UUID Studio

Color Converter

Convert colors between hex, rgb(), and hsl().

  • 🔒 No data stored or uploaded
  • ⚡ 100% client-side
  • 🆓 Free, no account

Need more than one tool at a time? Open the full Workbench - or press Ctrl+K to jump to any tool.

Create or edit JSON here (syntax colors), then format, validate, or convert - same as MongoDB $binary UUID blobs on the Convert tab once detected.

New document

About Color Converter

Converting a colour between hex, RGB, HSL and the newer CSS colour spaces is mostly mechanical, with one exception that matters: hex and RGB are the same thing in different notation, but HSL is a different coordinate system, and round-tripping through it loses precision because both ends quantise to 8 bits per channel.

HSL is worth using where it matches how you think - lightness and saturation adjustments are far more intuitive than editing three hex pairs. Its weakness is that lightness is not perceptual: HSL yellow at 50% lightness looks much brighter than HSL blue at 50% lightness, so a palette built by holding L constant will not look evenly weighted.

That is precisely what the newer spaces fix. OKLCH, now supported in every major browser, has a genuinely perceptual lightness axis, so holding L constant across hues produces colours that look equally bright - which makes it markedly better for generating palettes and for programmatic lightening and darkening. It also reaches colours outside sRGB on displays that can show them.

The other practical concern is contrast. WCAG requires a contrast ratio of at least 4.5:1 for normal text and 3:1 for large text, and the ratio is computed from relative luminance, not from any of these coordinate systems - so you cannot judge it from the numbers by eye. Two colours with the same HSL lightness can have very different contrast against white.

Conversion runs in your browser and nothing is transmitted.

How to use the Color Converter

  1. Paste a colour in any notation - #RRGGBB, #RGB, rgb(), hsl(), or a named colour.
  2. Read the equivalents, and note that the 8-digit hex and rgba() forms carry alpha.
  3. Use OKLCH when you are building a palette or adjusting lightness programmatically.
  4. Check the contrast ratio against your background before using a colour for text.

Examples

  • Hex
    #5eead4
  • rgb()
    rgb(94, 234, 212)
  • hsl()
    hsl(174, 70%, 60%)

Color Converter in code

The same operation this tool performs, in the languages you are most likely to need it.

JavaScript
const hexToRgb = (hex) => {
  const h = hex.replace("#", "");
  // Expand the 3-digit shorthand: #abc -> #aabbcc
  const full = h.length === 3 ? [...h].map((c) => c + c).join("") : h;
  return {
    r: parseInt(full.slice(0, 2), 16),
    g: parseInt(full.slice(2, 4), 16),
    b: parseInt(full.slice(4, 6), 16),
  };
};

const rgbToHex = ({ r, g, b }) =>
  "#" + [r, g, b].map((v) => v.toString(16).padStart(2, "0")).join("");
  // padStart matters: 10 -> "0a", not "a"

// WCAG contrast ratio - what actually determines readability
const luminance = ({ r, g, b }) => {
  const [R, G, B] = [r, g, b].map((v) => {
    const s = v / 255;
    return s <= 0.03928 ? s / 12.92 : ((s + 0.055) / 1.055) ** 2.4;
  });
  return 0.2126 * R + 0.7152 * G + 0.0722 * B;
};

const contrast = (a, b) => {
  const [x, y] = [luminance(a), luminance(b)].sort((m, n) => n - m);
  return (x + 0.05) / (y + 0.05);
};
// >= 4.5 for normal text, >= 3 for large text
CSS - modern colour
/* OKLCH: perceptual lightness, so a palette built by varying
   L alone looks evenly weighted - which HSL does not. */
:root {
  --brand:       oklch(0.62 0.19 256);
  --brand-light: oklch(0.78 0.14 256);   /* same hue, lighter */
  --brand-dark:  oklch(0.44 0.19 256);
}

/* Derive variants from one value instead of hand-picking hex */
.button:hover { background: oklch(from var(--brand) calc(l + 0.08) c h); }

/* Modern alpha syntax - no separate rgba()/hsla() needed */
color: rgb(59 130 246 / 50%);
color: hsl(217 91% 60% / 50%);

/* color-mix() for blending */
background: color-mix(in oklch, var(--brand), white 20%);

/* Wider gamut where the display supports it */
@supports (color: color(display-p3 1 0 0)) {
  .vivid { color: color(display-p3 1 0 0); }
}

When you need this

  • Converting a hex colour from a design file into rgb() or hsl() for CSS.
  • Building a set of lighter and darker variants from one brand colour.
  • Checking a text and background pair against WCAG contrast requirements.
  • Translating a colour between a design tool and code.

Common problems and what causes them

Missing zero padding in hex output
Channel value 10 must render as '0a'. Without padStart it becomes 'a' and the hex string is five characters, which either fails to parse or is read as a different colour.
Assuming HSL lightness is perceptual
hsl(60 100% 50%) - yellow - looks far brighter than hsl(240 100% 50%) - blue - at the same lightness. A palette built by holding L constant in HSL will not look evenly weighted. OKLCH fixes this.
Precision lost round-tripping through HSL
Both ends quantise to 8 bits per channel, so hex to HSL to hex does not always return the original value. Keep one canonical representation rather than converting back and forth.
Judging contrast by eye or by lightness
WCAG contrast is computed from relative luminance with per-channel gamma correction, so it does not follow from HSL lightness. Two colours with identical L can have very different contrast against white. Compute the ratio.
Forgetting the 3-digit shorthand
#abc means #aabbcc, not #0abc00. A parser that does not expand it produces a completely wrong colour, and the input is common in hand-written CSS.
Alpha channel dropped
An 8-digit hex (#RRGGBBAA) and rgba() carry transparency that 6-digit hex and rgb() cannot. Converting between them silently discards the alpha.

FAQ

What is the difference between hex, RGB and HSL?
Hex and RGB are the same values in different notation - three 8-bit channels. HSL is a different coordinate system (hue, saturation, lightness) over the same sRGB colours, which is easier to reason about for adjustments but quantises on conversion, so round-tripping can lose precision.
Should I use OKLCH?
For palettes and programmatic lightness adjustment, yes - it is supported in all major browsers and its lightness axis is genuinely perceptual, so equal L means equal apparent brightness across hues. HSL does not have that property, which is why HSL-derived palettes often look uneven.
How do I check colour contrast?
Compute the WCAG ratio from both colours' relative luminance: at least 4.5:1 for normal text and 3:1 for large text. It cannot be judged from HSL lightness or by eye - the formula applies per-channel gamma correction first.
What does #abc mean?
It is the 3-digit shorthand where each digit is doubled, so #abc is #aabbcc. Any hex parser needs to expand it, and forgetting to is a common source of wrong colours.
How do I add transparency to a hex colour?
Append two more digits for alpha: #RRGGBBAA, where FF is opaque and 00 fully transparent. Modern CSS also accepts rgb(59 130 246 / 50%), which is usually clearer.
Does it support alpha/transparency (rgba, hsla, #rrggbbaa)?
Not currently - this focuses on solid colors in hex, rgb(), and hsl(). Strip the alpha channel before converting if your source includes one.
Why do the RGB and hex values sometimes round differently than expected?
HSL to RGB conversion involves floating-point math that gets rounded to the nearest integer byte value, so round-tripping hex → HSL → hex can occasionally shift a value by 1 - this is normal floating-point rounding, not a bug.

Related reading