HEX vs RGB: Which Color Format Should You Use?
HEX vs RGB: Which Color Format Should You Use?
Open any stylesheet and you will find the same color written two different ways:
#3B82F6 in one place and rgb(59, 130, 246) in another. They render the exact
same blue, yet developers argue about which to use in CSS, design tokens, and
component libraries. The truth is that HEX and RGB are two notations for
the same underlying values — the choice is about readability, alpha support,
and tooling. When you need to switch between them instantly, our
Color Converter turns any HEX into RGB, HSL, and back — entirely
in your browser, so nothing is uploaded.
This guide explains what each notation actually encodes, why they are interchangeable, where each one wins, the traps that bite almost everyone, and when a converter beats doing the math by hand.
What Are HEX and RGB?
Both formats describe a color as three channels — red, green, and blue — each ranging from 0 to 255. They only differ in how those numbers are written.
- HEX encodes each channel as a two-digit hexadecimal number and joins them
after a
#.#3B82F6means red3B(59), green82(130), blueF6(246). - RGB writes the same channels as plain decimals in a function:
rgb(59, 130, 246).
Because both cover the identical 0–255 range per channel, every HEX color has an exact RGB equivalent and vice versa. There is no color one can express that the other cannot (with one historical exception — alpha — covered below).
Mental model: HEX and RGB are the same three numbers in different bases.
F6and246are the same value; one is base 16, the other base 10.
How the Two Formats Compare
| Concern | HEX | RGB |
|---|---|---|
| Notation | #RRGGBB (base 16) | rgb(r, g, b) (base 10) |
| Compactness | Very compact (#fff) | More verbose |
| Human-readable channels | No (mental hex math) | Yes (plain decimals) |
| Alpha / transparency | #RRGGBBAA (modern) | rgba(r, g, b, a) |
| Easy to tweak in code | Harder (string slicing) | Easier (numeric math) |
| Shorthand | Yes (#f00 = #ff0000) | No |
Neither is "better" universally. HEX is unbeatable for terse, copy-paste color constants; RGB shines when a value must be computed — fading, mixing, or generating a palette programmatically.
Why the Distinction Matters
The format you pick affects real workflows:
- Design handoff — designers usually copy HEX from tools like Figma, so HEX tends to dominate design tokens and brand guidelines.
- Dynamic color — animating a background from one shade to another is trivial with numeric RGB channels but awkward with hex strings.
- Alpha transparency —
rgba()has expressed opacity for two decades; 8-digit HEX (#RRGGBBAA) is newer and not supported in very old browsers. - Accessibility math — WCAG contrast formulas operate on linear RGB channels, so you convert to RGB numbers first. Our Color Contrast Checker does exactly that behind the scenes.
Code Examples
JavaScript
// HEX -> RGB: parse two hex digits per channel
function hexToRgb(hex) {
const h = hex.replace("#", "");
const full = h.length === 3 ? [...h].map((c) => c + c).join("") : h;
const n = parseInt(full, 16);
return { r: (n >> 16) & 255, g: (n >> 8) & 255, b: n & 255 };
}
// RGB -> HEX: pad each channel to two hex digits
function rgbToHex(r, g, b) {
return "#" + [r, g, b].map((v) => v.toString(16).padStart(2, "0")).join("");
}
console.log(hexToRgb("#3B82F6")); // { r: 59, g: 130, b: 246 }
console.log(rgbToHex(59, 130, 246)); // "#3b82f6"
Python
def hex_to_rgb(hex_str):
h = hex_str.lstrip("#")
if len(h) == 3: # expand shorthand #f00 -> #ff0000
h = "".join(c * 2 for c in h)
return tuple(int(h[i:i + 2], 16) for i in (0, 2, 4))
def rgb_to_hex(r, g, b):
return "#{:02X}{:02X}{:02X}".format(r, g, b)
print(hex_to_rgb("#3B82F6")) # (59, 130, 246)
print(rgb_to_hex(59, 130, 246)) # "#3B82F6"
Both runtimes prove the point: converting between HEX and RGB is pure formatting, never a loss of information.
Common Pitfalls
- Forgetting shorthand expansion —
#f00is#ff0000, not#0f0000. Each digit doubles; handle the 3-digit case before parsing. - Dropping the leading zero — the channel
10(decimal 16) is hex0A, notA. Always pad to two digits or#3b8breaks. - Mixing up alpha scales —
rgba()alpha is0–1(e.g.0.5), but 8-digit HEX alpha is00–FF(e.g.80). They are not the same number. - Assuming HEX is case-sensitive —
#3B82F6and#3b82f6are identical; never rely on case to carry meaning. - Trying to interpolate hex strings — animating
"#000"toward"#fff"by string math produces garbage. Convert to RGB numbers, interpolate, convert back.
Hands-on: Tested with the Tool
I opened the Color Converter and pasted the HEX value #3B82F6
(the classic Tailwind "blue-500"). The tool immediately produced the matching
notations, which I confirmed against my own calculation:
- RGB:
rgb(59, 130, 246) - HSL:
hsl(217, 91%, 60%)
Reading the channels back by hand lines up exactly: 3B = 59, 82 = 130,
F6 = 246. I then typed the RGB value rgb(255, 87, 51) into the same tool and
it returned HEX #FF5733 and hsl(11, 100%, 60%) — a perfect round-trip with no
drift in either direction.
To sanity-check the numbers independently, I reproduced them in Python:
import colorsys
r, g, b = 59, 130, 246
h, l, s = colorsys.rgb_to_hls(r/255, g/255, b/255)
print(round(h*360), round(s*100), round(l*100)) # 217 91 60
The script printed 217 91 60, matching the tool's HSL output exactly. The
takeaway from the live test: HEX and RGB are lossless mirrors of each other, and
the converter is simply the fastest way to move a color between the notation your
CSS wants and the one your design tool gave you.
Related Tools
- Convert any HEX, RGB, or HSL value with the Color Converter.
- Check WCAG readability with the Color Contrast Checker.
- Build matching schemes with the Color Palette Generator.
- Generate lighter and darker steps with the Tints & Shades Generator.
- Derive complementary and triadic sets with the Color Harmonies Generator.
When to Use a Tool Instead of Code
You can write a five-line hexToRgb() helper, so why open a converter? For the
same reason you reach for a JSON Formatter: when a color shows
up in a design file, a bug report, or a Slack message and you need the other
notation right now — no scratch file, no REPL, no risk of a shorthand or
padding mistake. Keep small conversion helpers in production code where they run
at runtime; for ad-hoc lookups, contrast checks, and confirming a suspicious
shade, the browser tool is faster and gives you HSL and alpha in the same view.