EyeDropper Color Picker — Free window.EyeDropper Screen Sampler

EyeDropper Color Picker · Buttons · Plain HTML, CSS & JS · Live preview

Share & Support

What's included

Features

Real EyeDropper API
new EyeDropper().open() samples an actual screen pixel.
Whole-screen sampling
Not limited to page content — any visible pixel counts.
Gesture-gated call
Invoked directly from the click handler, as the API requires.
Graceful cancel handling
AbortError from Escape/click-away restores idle state, no error UI.
Feature-detected fallback
Manual hex input swaps in when window.EyeDropper is missing.
Shared render path
applyColor() renders picks and manual entries identically.
Running palette
Deduped, capped chip list of every picked color.
One-click copy
Copies the current hex to the clipboard with confirmation.

About this UI Snippet

EyeDropper Color Picker — Sampling Real Screen Pixels, With a Manual Fallback

Screenshot of the EyeDropper Color Picker snippet rendered live

Most "color picker" widgets on the web are really just <input type="color"> wrappers — a swatch grid or a saturation square you drag inside. This one is different: it uses the actual window.EyeDropper API to let the user sample a pixel from *anywhere on their screen*, not just inside the page, then builds a running palette from what's picked.

The real API: new EyeDropper().open()

window.EyeDropper is a constructor. Calling new EyeDropper().open() inside a click handler switches the cursor into a magnifier and resolves a promise with { sRGBHex: '#rrggbb' } once the user clicks anywhere — another browser tab, the OS taskbar, a design file open in a different app. It must be invoked from a direct user gesture (the click on "Pick a color") or the browser rejects it; that's why the pick call lives directly inside the button's click listener rather than behind any async setup.

Cancellation is not an error

Pressing Escape or clicking away rejects the promise with an AbortError DOMException. The code checks for that name specifically and restores the idle message instead of showing a scary "failed" state — cancelling a pick is a normal, expected outcome, not a failure.

Honest unsupported fallback

window.EyeDropper currently exists only in Chromium-based browsers (Chrome, Edge, Opera) — Firefox and Safari don't implement it. Rather than hide the feature or show a dead button, typeof window.EyeDropper === 'function' is feature-detected up front: if it's missing, the "Pick a color" button is hidden and a manual hex <input> takes its place, styled identically to the rest of the UI. Because applyColor() is the single function both paths call, the swatch, hex/RGB readout, palette, and copy button behave exactly the same whether the color came from a real screen sample or a typed value.

A palette that survives repeated picks

Every applied color — from either path — is pushed to the front of a picked array (deduped, capped at 12) and re-rendered as clickable chips, so a design session can build up a working set of colors without losing earlier picks. Pair this with a gradient picker for building multi-stop gradients from sampled colors, or a color swatch grid for a fixed brand palette.

Build with AI

Build, Understand, Optimize, and Extend It With AI

Paste this snippet's HTML, CSS, and JS into an AI coding assistant like Claude and ask it to explain why new EyeDropper().open() must be called synchronously from within a user-gesture event handler, and what would break if it were called after an await or inside a setTimeout instead. It's also useful for reasoning about the fallback: ask why the manual hex input and the real eyedropper both funnel into the same applyColor() function rather than having separate rendering logic for each path, and how that keeps the swatch, palette, and copy button behavior identical regardless of source. For extensions, ask it to add a "compare two colors" mode using two independent eyedropper picks, persist the palette to localStorage between sessions, or add an HSL readout alongside the existing hex/RGB values. Treat the code less like a finished artifact and more like a starting point for a conversation.

Prompt to recreate it

Copy this into your AI assistant of choice to build the effect from scratch, or as a jumping-off point for your own variant:

text
Build an "EyeDropper color picker" tool in plain HTML, CSS, and JavaScript using the real browser window.EyeDropper API — no libraries.

Requirements:
- A "Pick a color" button that, on click, calls new EyeDropper().open() directly and synchronously inside the click handler (required because the API only works from a direct user gesture), and on success applies the returned sRGBHex value to a swatch element, a hex text readout, and an RGB text readout computed from the hex.
- Wrap the open() call in a try/catch. If the promise rejects with a DOMException named AbortError (the user pressed Escape or clicked away to cancel), show a neutral "cancelled" status message rather than an error. For any other rejection, show a status message naming the error and suggesting the manual fallback.
- CRITICAL: feature-detect support with typeof window.EyeDropper === 'function' before wiring up the button. If unsupported (which is the common case — this API currently only exists in Chromium-based browsers, not Firefox or Safari), hide the pick button entirely and show a manual hex color text input in its place, styled to match the rest of the UI. Route both the real eyedropper result and the manual input's value through the exact same "apply color" function so the swatch, RGB readout, and everything downstream behaves identically regardless of which path produced the color.
- Maintain a running palette: every applied color (whether picked or manually typed) gets added to a deduplicated list of clickable swatch chips capped at a reasonable size (e.g. 12), each of which re-applies that color when clicked, plus a "Clear" control to empty the palette.
- Add a "Copy" button next to the current hex value that copies it to the clipboard via navigator.clipboard.writeText with a brief "Copied!" confirmation state.

Want to tighten it up first? Run this prompt through the AI Prompt Studio to score it across 8 quality dimensions, catch anti-patterns, and tune the wording for Claude, ChatGPT, or Gemini before you paste it in.

Step by step

How to Use

  1. 1
    Paste HTML, CSS, and JSThe swatch, hex/RGB readout, and palette render immediately.
  2. 2
    Click "Pick a color"In a supporting browser, your cursor becomes a magnifier.
  3. 3
    Click any pixel on screenAnother tab, the OS, another app — the real color is sampled.
  4. 4
    Press Escape to cancelThe pick aborts cleanly with no error shown.
  5. 5
    Unsupported browser?A manual hex input appears in place of the button automatically.
  6. 6
    Build a paletteEvery applied color adds a clickable chip you can revisit or clear.

Real-world uses

Common Use Cases

Design tools
Sample any on-screen color into a gradient picker.
Brand palette builders
Collect sampled colors alongside a color swatch grid.
CSS/theme editors
Grab a real color from a mockup to seed a theme.
Accessibility contrast checks
Sample foreground/background pairs to test contrast.
Illustration/whiteboard apps
Match a stroke color to something already on screen.
QA/design review tools
Quickly report the exact hex of a rendering bug.

Got questions?

Frequently Asked Questions

It currently ships in Chromium-based browsers — Chrome, Edge, and Opera — from Chrome 95 onward. Firefox and Safari do not implement it as of this writing. The snippet feature-detects with typeof window.EyeDropper === 'function' and swaps in a manual hex input when it's missing, so the demo works everywhere either way.

The EyeDropper API requires a direct user gesture (a click, tap, or key press) to open, as a security measure against pages silently sampling the screen. That's why new EyeDropper().open() is called synchronously inside the button's own click listener rather than after any await or setTimeout, which would break the gesture chain and cause the browser to reject the call.

Pressing Escape or clicking outside the eyedropper's active area rejects the open() promise with a DOMException named AbortError. The code checks err.name === 'AbortError' specifically and shows a neutral "cancelled" message rather than an error, since cancelling is a normal, expected user action, not a failure.

Yes — that's the defining feature of the EyeDropper API versus a regular color input. Once open() is called, the browser lets the user click anywhere visible on their screen, including other applications, the OS desktop, or another monitor, and returns the sRGB hex of whatever pixel was clicked.

Feature-detect window.EyeDropper once (e.g. in a memoized value or computed property), conditionally render either the pick button or the manual hex input based on it, and call new EyeDropper().open() inside the button's onClick handler exactly as here — keep it synchronous with the click so the user-gesture requirement is preserved. Store the resulting hex in component state and derive the RGB/swatch/palette from that single value.