A hex colour and an rgb() colour are the same three numbers written two ways. #4F46E5 is just 79, 70, 229 in base 16 — two hex digits per channel, each holding 0 to 255. Converting between them is arithmetic. The interesting part is what those numbers actually mean, because it is not what most people assume.
Shorthand doubles each digit, it does not pad
Three-digit hex expands by repeating each character: #f00 becomes #ff0000, not #f00000. The rule exists so that the shorthand spans the full range — #fff has to be pure white, and it only can if f becomes ff.
The consequence is that shorthand cannot express most colours. Only 4,096 of the 16.7 million are reachable, because each channel is limited to the sixteen values 00, 11, 22 … ff. #4F46E5 has no three-digit form. Shorthand is a convenience for round numbers, not a compression scheme.
The number is not brightness — this is the big one
Here is the fact that surprises almost everyone, and it causes real bugs in real design systems. #808080 sits exactly halfway between #000000 and #FFFFFF numerically. It is not halfway in brightness. It emits about 21.6% of the light that white does.
The reason is that sRGB — the colour space every hex code on the web lives in — is gamma-encoded rather than linear. The encoding deliberately devotes more of the available values to dark tones, because human vision is far more sensitive to differences down there. So the numbers are perceptually spaced, not physically spaced. The grey that actually emits half the light of white is around #BCBCBC, which looks nothing like a "middle" grey when you write it down.
This matters the moment you do arithmetic on colours. Averaging #000000 and #FFFFFF by adding the channels and halving gives #808080 — a colour with 21.6% of white's luminance, presented as if it were the midpoint. Doing the same in linear space gives #BCBCBC. This is why naive gradients between saturated colours pass through a muddy dark band, why blurring and resizing images in gamma space darkens them, and why blending code that looks obviously correct produces results that look subtly wrong.
Eight digits, and what this tool does not do
CSS Color Module Level 4 added an alpha channel to hex: #RRGGBBAA, where the last pair is opacity — #FF0000 80 is red at 50%. There is a four-digit shorthand too, #RGBA, expanding the same way. Every current browser supports both.
This tool handles six digits and three, and stops there — the input is capped at seven characters including the hash. If you are working with transparency, rgba() or the modern space-separated rgb(255 0 0 / 50%) is the clearer notation anyway, because an opacity written as a hex pair is unreadable to everyone including you in six months.
Both notations describe sRGB, and that is now a limitation
A hex code carries no information about which colour space it means; the web simply agreed it is sRGB, a standard defined in 1996 around the capabilities of CRT monitors. That worked while every screen was roughly the same. It works less well now that most phones and laptops can display a noticeably wider range of colours.
This is why CSS gained colour functions like oklch() and color(display-p3 …). They can express saturated colours that no hex code can reach — a red more vivid than #FF0000. If your brand red looks flat on a modern display, that is the ceiling you have hit, and no amount of adjusting hex digits will get past it. For everyday interface work, though, sRGB remains the safe common denominator, and hex remains the shortest way to write it.
Common questions
Is anything sent to a server?
No. This tool is marked "client": the conversion is a few lines of arithmetic running in your browser tab. Nothing is transmitted and nothing is stored.
Why does the midpoint between two of my colours look wrong?
Almost certainly the gamma issue described above. Averaging hex values treats sRGB numbers as if they were quantities of light, and they are not — they are perceptually encoded. To blend two colours correctly, convert each channel to linear light, average there, then convert back. Or use a colour space designed for it: interpolating in Oklch gives smooth results without the muddy band, and CSS supports it directly in gradients now.
Is hex better than rgb()?
They are identical in what they can express, so it is a question of readability. Hex is shorter and dominates design tools, which is why most codebases use it. rgb() is easier to reason about when a value comes from a variable or a calculation, and the modern rgb(255 0 0 / 50%) syntax handles alpha more legibly than an eight-digit hex ever will. Consistency within a codebase matters more than the choice itself.
Does the case of the letters matter?
No. #FF0000 and #ff0000 are the same colour to every parser. Lowercase is the more common convention in CSS and what most formatters produce; uppercase is more common in design tools. Pick one and let a formatter enforce it, because mixed case in a codebase makes colours harder to grep for than it has any right to.
How do I get a lighter or darker version of a colour?
Not by multiplying the hex channels, which is the intuitive move and produces the muddy results described above. Convert to HSL or, better, Oklch, adjust the lightness, and convert back. Oklch is worth the learning curve here because its lightness axis is perceptually uniform: adding ten points of lightness looks like the same step regardless of the hue you started from, which is exactly what a colour ramp in a design system needs and exactly what HSL fails to give you.