Designers hand off hex strings. Developers paste them. And three times out of ten the string is fine and the render is still wrong — because a hex value is not a color, it's a set of numbers that each platform reads differently.
1. Eight digits, two different channel orders
CSS defines 8-digit hex as #RRGGBBAA — alpha last. Android, Flutter and Kotlin define it as #AARRGGBB — alpha first. So #80FF0000 is:
-
CSS: red
0x80, green0xFF, blue0x00, alpha0x00→ completely invisible. Your UI element quietly disappears. -
Android: alpha
0x80, red0xFF, green0x00, blue0x00→ a 50% red overlay.
Same literal, opposite meaning, no error anywhere. Six-digit hex is safe because all three channels are present in the same order; the moment you add the fourth pair you have an ambiguous string. Hand off rgba(255, 0, 0, 0.5) or a 6-digit hex plus a separate opacity token instead.
2. Alpha is not a color (so don't pre-blend it)
Converting a translucent overlay into a solid hex "so it fits the palette" only works against one background:
-
rgba(0, 0, 0, 0.5)over#FFFFFF→#808080 -
rgba(0, 0, 0, 0.5)over#3366CC→#1A3366
Pre-blending bakes in the surface it happened to sit on. The same 50% black is mid-grey on a white card and dark navy on a blue hero. Keep alpha as alpha, or record which surface the hex was measured against.
3. Hex carries no color space
A hex code says nothing about gamut. The same #FF0000 is a different physical color on an sRGB laptop panel and a Display P3 phone — and a color you sample from a wide-gamut screenshot is P3 coordinates wearing an sRGB costume, which is why saturated colors read duller or hotter than the designer's file. CSS color(display-p3 …) exists precisely because 8-bit hex can't express what those screens can show.
None of these are exotic edge cases — they show up in handoff, in dark-mode overlays, and in "the color looks different on my machine". What they share is that the number is right and the format is wrong.
💡 When I'm chasing one of these, I use the CodeToolbox color picker to see the same color as HEX, RGB, HSL and oklch side by side — it's client-side, so I can paste in a value without uploading a screenshot anywhere.
Which one has bitten you? For me it's #2 — every translucent overlay we ever "simplified" into a hex eventually sat on a different background.
Top comments (0)