Color Converter

Runs entirely in your browser

Convert between HEX, RGB, HSL, and HSV color formats instantly.

Color Preview

HEX

Hexadecimal

Supports 3-char (#RGB) and 6-char (#RRGGBB) formats

RGB

Red, Green, Blue (0-255)

Standard CSS format

rgb(79, 70, 229)

Modern CSS format

rgb(79 70 229)

HSL

Hue, Saturation, Lightness

Standard CSS format

hsl(243, 75%, 59%)

Modern CSS format

hsl(243 75% 59%)

HSV

Hue, Saturation, Value

Display format

hsv(243, 69%, 90%)
Runs entirely in your browser — nothing is uploaded
Runs entirely in your browser. No uploads. Your files stay private.

What is Color Conversion?

Color conversion is the math of expressing the same point in colour space using different coordinate systems. HEX, RGB, HSL, and HSV all describe colours that ultimately map to the same sRGB-gamut pixels your monitor produces; the difference is which axes you reason about while picking and tweaking the value.
This converter implements the conversion math directly in TypeScript - no external colour library. The functions you can read in the source above (rgbToHsl, hslToRgb, rgbToHsv, hsvToRgb) are textbook implementations of the algorithms specified in the W3C CSS Color Module Level 4 reference. Every keystroke updates all four representations synchronously by routing through RGB as the canonical pivot, so round-trips never accumulate drift beyond integer rounding.
HEX is just RGB written in base-16. #FF0000 is exactly rgb(255, 0, 0) - one byte per channel, two hex digits per byte, six digits total. The 3-digit shorthand (#F00) doubles each digit, which is why only colours like #FFCC00 (= #FC0) compress losslessly. The picker control here uses the native HTML5 <input type=&quot;color&quot;> element, which always emits 6-digit HEX regardless of how the OS's colour picker is rendered.
RGB sits closest to the hardware: every monitor pixel is a triple of red, green, and blue subpixels, each driven by an 8-bit value. RGB is great for compositing and direct pixel work but unintuitive for design work because moving towards a darker shade of the same hue requires changing all three channels in proportion.
HSL is the format of choice for most design systems because the three axes match how humans describe colour: hue (which colour, on a 0-360 colour wheel), saturation (how vivid, 0-100%), and lightness (how bright, 0-100% where 50% is the pure colour and 100% is white). Tweaking lightness alone gives you light/dark variants; tweaking saturation alone gives you muted variants. The CSS custom-property pattern --primary-h, --primary-s, --primary-l owes its existence to this property.
HSV (sometimes called HSB) is HSL's cousin, used heavily in colour pickers like the one in Photoshop and Figma. The difference is the third axis: HSL's lightness puts pure white at 100% and pure black at 0%, with the most saturated version of the hue at 50%. HSV's value puts the most saturated hue at 100% and black at 0%, with white as a desaturation of any hue at value 100%. HSV maps more naturally to a square colour-picker swatch; HSL maps better to design tokens.
Two practical limits worth knowing. First, all four formats here are confined to the sRGB gamut - they cannot describe wider-gamut colours like Display P3 or Rec. 2020. For those, CSS Color Level 4 introduces oklch() and color() syntax, which this tool does not yet support. Second, integer rounding means a HEX -> HSL -> HEX round-trip can land one digit off in extreme corners of the gamut; the canonical pivot through RGB keeps drift bounded but not zero.

Common Use Cases

01

Building a design-token palette

Pick a base hue in HSL and step lightness in 10% increments to generate the 50/100/200/.../900 shades modern design systems expect.

02

Translating Figma to CSS

Copy an HSV value out of Figma's colour panel and paste it here to get the equivalent HEX and modern hsl() syntax for your stylesheet.

03

Theming with CSS variables

Store HSL components separately (--h, --s, --l) so you can change saturation or lightness without touching hue when switching between light and dark modes.

04

Accessibility contrast prep

Adjust HSL lightness to push a foreground/background pair past WCAG AA (4.5:1) before plugging the result into a contrast checker.

Frequently Asked Questions

They describe the same number in different bases. HEX writes each 0-255 channel as a 2-digit base-16 value, RGB writes it in decimal. #FF0000 and rgb(255, 0, 0) are bit-identical pure red. HEX is more compact (6 chars vs ~14) and round-trips losslessly through CSS, JSON, and most design tools.
HSL separates hue from intensity, so you can darken, lighten, or desaturate a colour by moving one axis instead of recomputing three correlated channels. That's why design systems built around CSS variables almost always store H, S, L separately - one swap of the hue token recolours the whole UI.
Both share the hue axis, but the third axis differs. HSL's lightness puts the pure hue at 50% and grows to white at 100%. HSV's value puts the pure hue at 100% and grows darker towards 0%. Picker UIs like Photoshop's use HSV because it maps to a saturation/value square; CSS prefers HSL because lightness is a more intuitive design knob.
HEX, rgb(), and hsl() are universally supported. CSS Color Level 4 also adds the comma-free space-separated syntax (rgb(255 0 0) and hsl(0 100% 50%)), an alpha-via-slash syntax (rgb(255 0 0 / 0.5)), plus newer formats like oklch() for wide-gamut work. HSV has no native CSS function - you convert it to HSL or HEX first.
Yes - the parser doubles each digit, so #F0A becomes #FF00AA. Only colours where each channel is a repeated digit (#11, #22, ..., #FF) can be expressed in shorthand, which is why #FFCC00 abbreviates but #FECC01 does not.
The simplest pattern is '#' + Math.floor(Math.random() * 16777215).toString(16).padStart(6, '0'), which is exactly what the random button uses. The number 16777215 is 0xFFFFFF, the largest 24-bit value. For perceptually-even random palettes, generate hue uniformly in HSL with fixed saturation/lightness instead.
All four formats here use integer channels (0-255 for RGB, 0-360 / 0-100 for HSL/HSV). Conversions introduce sub-integer rounding, so a far-corner colour like #010203 may bounce to HSL(210, 50%, 1%) and back to #010204. The drift is at most one channel unit and never compounds across more conversions.
Not yet. The tool focuses on the opaque colour space; for alpha you can manually wrap the output as rgba() or rgb(R G B / 0.5) using the modern slash syntax. Alpha doesn't change between formats - it's the same number regardless of which colour space you express the RGB part in.
No. Pantone is a proprietary spot-colour catalogue, CMYK is a print-process colour space (and depends on paper and ink profiles), and Lab/oklch require gamut mapping that's beyond a single-button conversion. For those, use a calibrated tool like Adobe Color or a print colour bridge.
Convention is uppercase (#FF0000) in design specs and CSS variables, but the parser is case-insensitive and accepts #ff0000, #Ff0000, anything. Modern tools mostly emit uppercase for readability; this tool follows that convention and normalizes input to uppercase on display.

Advertisement