sRGB Hex vs rgb() vs hsl(): Same Triple, Three Spellings
Hex, rgb(), and hsl() are three spellings of one 8-bit opaque sRGB triple. CSS Color Module Level 4 (W3C CRD, 6 August 2026) expands #RGB by duplicating each nibble: #36c is #3366cc, which is rgb(51, 102, 204) and hsl(220, 60%, 50%). HSL uses the Level 4 hslToRgb / rgbToHsl sample functions; bytes are Math.round(channel * 255). Not Display P3. Nothing is uploaded.
A hex code is not a different color model from rgb(). Both name the same three 0–255 channels. HSL is a cylindrical view of that same sRGB cube, not P3 or Lab. The live color converter maps those three spellings in the browser. This page names the expansion, the legacy comma syntax, and the 8-bit round-trip.
Three-digit hex duplicates nibbles
#36c is #3366cc, not #00306c
Level 4 §5.2: a 3-digit #RGB token is the 6-digit form obtained by duplicating each digit. The spec example is #123 → #112233 (rgb(17, 34, 51)). Load sample #3366cc is the same triple as #36c or 36C (the # is optional here; CSS itself requires it). Letters are case-insensitive: #00ff00 equals #00FF00. Output hex is lowercase #RRGGBB. Three-digit hex names 4096 colors; six-digit hex names 16,777,216.
4-digit and 8-digit hex carry alpha
Level 4 also defines #RGBA and #RRGGBBAA. Those expand the same way, but the extra nibble is opacity. This page converts opaque sRGB only, so a 4-digit or 8-digit body is rejected before any expand. rgba() and hsla() are rejected for the same reason.
Legacy commas, not modern spaces
rgb() here is integers 0–255 with commas
CSS Color Level 4 keeps a legacy color syntax for Web compatibility: components separated by commas. The converter accepts only rgb(51, 102, 204) — integers, inclusive 0–255, not clamped. rgb(300, 0, 0) is an error, not #ff0000. Modern space-separated rgb(51 102 204), percentages, and slash-alpha rgb(51 102 204 / 0.5) are rejected. Convert is a button. Copy writes the hex, rgb(), and hsl() lines.
hsl() hue is a unitless degree, then wrapped
Legacy hsl() here is hsl(220, 60%, 50%): a unitless hue in degrees, then percent saturation and lightness (0–100, not clamped). Hue wraps with ((h % 360) + 360) % 360, so hsl(-140, 60%, 50%) and hsl(580, 60%, 50%) are the same sample blue. Units such as deg / rad / turn are rejected. HSL → sRGB uses the Level 4 §7.1 hslToRgb sample (f(0), f(8), f(4)); 0–1 channels become bytes with Math.round(channel * 255).
8-bit round-trip, missing hue
50% lightness is not a 127.5 byte
sRGB → HSL uses Level 4 §7.2 rgbToHsl. For #3366cc the channels are 51/255, 102/255, 204/255 — hue 220, saturation 60, lightness 50 — so the three spellings round-trip. Gray is different: hsl(0, 0%, 50%) has light 0.5, and Math.round(0.5 * 255) is 128, which is #808080. 128/255 is 50.196…%, serialized to one decimal as hsl(0, 0%, 50.2%). The swatch is background-color set to that computed hex.
Achromatic hue is missing, written as 0
When saturation is about 0, rgbToHsl sets hue to NaN (the spec’s missing / powerless hue; any hue would look the same). Legacy comma serialization cannot write none, so this page uses 0: #000000 is hsl(0, 0%, 0%) and #ffffff is hsl(0, 0%, 100%). That 0 is a serialization choice, not a stored red. Copy writes the three lines. Load sample fills #3366cc and does not run Convert. This is not a named-color table, not color(), not Display P3, and not a WCAG contrast checker.
Convert an opaque sRGB color in the browser
Hex, rgb(), and hsl() of the same 8-bit triple. Nothing is uploaded.
Use Color Converter →FAQ
- Are #36c and #3366cc different colors?
- No. CSS Color Module Level 4 (W3C CRD, 6 August 2026) expands 3-digit hex by duplicating each nibble: #36c is #3366cc, which is rgb(51, 102, 204). The spec’s own example is #123 → #112233. That is not #00306c and not #36c000. Three-digit hex can name only 4096 colors (16³); six-digit hex can name 16,777,216. Load sample is #3366cc.
- Why does rgb(20% 40% 80%) fail here?
- This page accepts only the legacy comma form with integers 0–255: rgb(51, 102, 204). Values are not clamped, so rgb(300, 0, 0) is an error. CSS Color Level 4 also defines a modern space-separated syntax, percentages, slash-alpha (rgb(51 102 204 / 0.5)), and rgba(). Those are rejected. Convert is a button, not as-you-type.
- Why is gray hsl(0, 0%, L%) instead of keeping the input hue?
- The Level 4 rgbToHsl sample sets hue to NaN when saturation is about 0 (the spec treats that hue as missing / powerless). Serialization for the legacy comma form cannot write none, so this page uses 0: #808080 is hsl(0, 0%, 50.2%). 128/255 is not exactly 50%; Math.round(0.5 * 255) is 128, so hsl(0, 0%, 50%) still lands on #808080 and then serializes as 50.2%.
- Is this Display P3, a named color, or a contrast checker?
- No. Hex, rgb(), and hsl() here are the same 8-bit opaque sRGB triple. Named colors (rebeccapurple), color(), Display P3 / Rec.2020, Lab / OKLCH / HWB, 4-digit / 8-digit hex, hsla(), hue units (deg/rad/turn), and WCAG contrast are out of scope. The swatch is CSS background-color set to the computed lowercase #RRGGBB. Nothing is uploaded.