BE AWESOME
Settings
Web Tools
📅 August 3, 2026 · ⏱️ 5 min read

Color Picker: One Color, Three Formats, Zero Drift

Hex, RGB, and HSL kept perfectly in sync from one canonical value, plus an eyedropper that only works because of a fairly new browser API.

This post is about Color Picker: One Color, Three Formats, Zero Drift
Try the Color Picker →

Pick a color once, get hex, RGB, and HSL all at the same time, each with its own copy button. It's a small, obvious idea, and I built it because I kept personally hitting the annoyance it solves: needing a color in a format some tool didn't happen to give me, then manually converting between color spaces by hand or pasting into yet another site just to get the one representation I actually needed at that moment.

The eyedropper only works because the browser recently started allowing it

Sampling any pixel on the actual screen, not just within the page, relies on a relatively new browser API that lets a page request permission to read a pixel color from anywhere the user points it, including outside the browser window entirely. That's powerful, and it's also not supported in every browser yet, which meant this couldn't be the tool's only way to pick a color. The eyedropper button gracefully disables itself when the API isn't available rather than being offered and then failing, and the native system color picker and manual hex entry both exist as fully capable fallbacks, not afterthoughts, so the tool works the same regardless of which specific way someone's browser lets them get a color in.

Keeping three color spaces in sync means one has to be the source of truth

Hex, RGB, and HSL all describe the same underlying color through different math, and letting any of the three be edited directly means every edit has to propagate correctly to the other two without drift or rounding loss creeping in over repeated conversions. I settled on keeping one canonical internal representation and deriving the other two from it fresh on every change, rather than trying to keep three independently-editable representations manually synchronized with each other. That avoids a whole category of subtle bugs where converting hex to HSL and back to hex doesn't quite return the original value due to rounding, which is a real and well-known trap in color-space conversion code if you're not deliberate about where the authoritative value lives.

Copy feedback needed to confirm without interrupting

Clicking copy next to any of the three format rows needed some visible confirmation that the copy actually happened, since clipboard writes are silent by default and a person can't otherwise tell whether their click landed or nothing occurred at all. A jarring modal or alert would be wildly disproportionate to how small the action is, so the confirmation here is a brief, quiet inline change on the button itself — enough to register out of the corner of your eye without demanding attention or breaking the flow of comparing several colors back to back. Getting the timing of that brief confirmation right, long enough to notice, short enough to not linger and feel stale, took a few rounds of just watching myself use the tool repeatedly until it stopped feeling either too abrupt or too slow.

Recent colors needed a rule for what counts as "recent"

The recent-colors history could have just appended every single color change, including every intermediate value while someone drags a hue slider around, which would flood the history with dozens of near- identical entries from one continuous gesture. Instead it only commits a color to history on a deliberate pick action — an eyedropper sample, a hex entry, a swatch click — not on every intermediate value during a drag. That distinction between "actively exploring a color" and "committing to one" mattered for keeping the history actually useful as a list of colors someone meant to keep, rather than a noisy log of every value the cursor passed through on the way there.

Hex entry needed to be forgiving about format, not just valid values

People type hex codes inconsistently — with or without a leading hash, in three-character shorthand or the full six-character form, sometimes in uppercase and sometimes lowercase. A strict parser that only accepts one exact format would reject perfectly valid input for no good reason other than a missing character the tool could easily infer. I made the hex field accept all of these common variations and normalize them internally, since a color picker that makes someone remember the exact syntax it expects, rather than just accepting the color they clearly meant, is solving the wrong problem — the goal is getting to the right color fast, not testing whether someone typed hex notation precisely by the book.

What this tool doesn't try to be

This isn't a palette or harmony tool — it doesn't suggest complementary or analogous colors the way the site's Color Palette Generator does. Building that overlap in would have meant either duplicating logic between two tools or awkwardly merging two different tools with different core purposes into one confusing interface. This tool answers one question well: what is this exact color, in every format I might need it in. Anything about relationships between multiple colors belongs somewhere else, and keeping that boundary clean felt more useful than trying to make one tool do both jobs adequately instead of one tool doing one job very well.

It's a genuinely small tool, and I keep noticing that the small tools in this batch are the ones where the actual engineering lives entirely in edge cases and format tolerance rather than in any headline feature. Nobody will ever list "accepts hex codes with or without a leading hash" as a reason they liked this tool. They'll just never notice it failed to accept a color they typed the way they naturally type it, which is exactly the point.

If there's a theme across everything I built on this particular day, it might be this: the smaller and more single-purpose a tool is, the more its actual quality lives entirely in how it handles the inputs someone wasn't expecting to think carefully about — a hex code missing a hash, a case-sensitivity toggle, a blank line in a pasted list. None of that is glamorous. All of it is the actual work.

Hello!