{"id":50722618,"url":"https://github.com/mthcht/chromapicker","last_synced_at":"2026-06-10T01:30:42.955Z","repository":{"id":353611132,"uuid":"1220155515","full_name":"mthcht/chromapicker","owner":"mthcht","description":"Browser extension: pixel-perfect color picker, page \u0026 image palette extraction, OKLCH color mixer, harmony generator, CSS gradient builder","archived":false,"fork":false,"pushed_at":"2026-04-24T16:05:21.000Z","size":101,"stargazers_count":0,"open_issues_count":0,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-24T18:10:46.623Z","etag":null,"topics":["browser-extension","chrome-extension","color-palette","color-picker","color-science","javascript"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mthcht.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-24T15:50:07.000Z","updated_at":"2026-04-24T16:05:25.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/mthcht/chromapicker","commit_stats":null,"previous_names":["mthcht/chromapicker"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/mthcht/chromapicker","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mthcht%2Fchromapicker","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mthcht%2Fchromapicker/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mthcht%2Fchromapicker/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mthcht%2Fchromapicker/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mthcht","download_url":"https://codeload.github.com/mthcht/chromapicker/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mthcht%2Fchromapicker/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34133404,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-09T02:00:06.510Z","response_time":63,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["browser-extension","chrome-extension","color-palette","color-picker","color-science","javascript"],"created_at":"2026-06-10T01:30:33.111Z","updated_at":"2026-06-10T01:30:37.976Z","avatar_url":"https://github.com/mthcht.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 🎨 Chromapicker\n\n\n\u003cimg width=\"128\" height=\"128\" alt=\"icon128\" src=\"https://github.com/user-attachments/assets/4991c32d-1237-489b-9158-f52b9f42fe4f\" /\u003e\n\n\u003e Pick, extract, mix and analyze colors from any web page - with OKLCH precision.\n\nA polished browser extension for developers, designers and anyone who works with color on the web. Pixel-perfect picking, full-page color extraction, image palette analysis, color mixing in perceptually uniform color spaces, harmony generators, and a CSS gradient builder - all in one extension.\n\nWorks in **Microsoft Edge**, **Google Chrome**, **Brave**, **Arc**, **Opera**, and any other Chromium-based browser (version 95 or later).\n\n\u003cimg width=\"1124\" height=\"674\" alt=\"Capture d\u0026#39;écran 2026-04-26 220732\" src=\"https://github.com/user-attachments/assets/86d70fe9-ddcf-463a-ba1d-ca834cce6415\" /\u003e\n\u003cimg width=\"351\" height=\"586\" alt=\"Capture d\u0026#39;écran 2026-04-26 220746\" src=\"https://github.com/user-attachments/assets/3fafacf9-6777-4882-a599-c3f792fb6a94\" /\u003e\n\u003cimg width=\"376\" height=\"587\" alt=\"Capture d\u0026#39;écran 2026-04-26 220814\" src=\"https://github.com/user-attachments/assets/12e5aaa2-cf3c-4668-b2ec-e54f3162358a\" /\u003e\n\u003cimg width=\"360\" height=\"642\" alt=\"Capture d\u0026#39;écran 2026-04-26 220831\" src=\"https://github.com/user-attachments/assets/191a3faa-54de-496f-b3df-b9a93ea39221\" /\u003e\n\u003cimg width=\"392\" height=\"656\" alt=\"Capture d\u0026#39;écran 2026-04-26 220847\" src=\"https://github.com/user-attachments/assets/d41dc024-c6b0-4bb0-a09d-850468b6086d\" /\u003e\n\u003cimg width=\"387\" height=\"636\" alt=\"Capture d\u0026#39;écran 2026-04-26 220858\" src=\"https://github.com/user-attachments/assets/4287dc81-14b4-4033-80bc-abeecb566119\" /\u003e\n\u003cimg width=\"392\" height=\"659\" alt=\"Capture d\u0026#39;écran 2026-04-26 220943\" src=\"https://github.com/user-attachments/assets/273a8da1-73a3-4355-8c18-5e9c31bddafc\" /\u003e\n\n---\n\n## Table of contents\n\n- [Features](#features)\n- [Installation](#installation)\n- [Usage](#usage)\n- [Permissions explained](#permissions-explained)\n- [Privacy](#privacy)\n- [Technical notes](#technical-notes)\n- [Development](#development)\n- [License](#license)\n\n---\n\n## Features\n\n### 🎯 Pixel-perfect picker\n\nClick the toolbar icon and press **Pick**, or press **Alt+P** from anywhere - the browser's native EyeDropper API turns your cursor into a magnifier and samples the exact pixel you click on. The hex code is automatically copied to your clipboard.\n\n- Works on images, videos, canvas, SVG, gradients - anything rendered to the screen\n- Press **Esc** to cancel mid-pick\n- On successful pick, a small toast appears on the page confirming what was captured\n\n### 🔎 Extract page palette\n\nThe **Extract** button scans the current page and returns every color actually used in it - walking the DOM and collecting `color`, `background-color`, border colors, and SVG fills/strokes from computed styles. Results are deduplicated and sorted by frequency of use.\n\n- Click a swatch to copy the hex code\n- Click the magnifier icon on a swatch to **highlight every element on the page using that color** - they get outlined with an accent border so you can see where the color lives in the design\n- **Copy all** or **Save all** to history\n\n### 🖼️ Extract image palette\n\nSame **Extract** button has a dropdown - pick \"From an image...\" and drop in any local image file. A k-means++ clustering algorithm identifies the dominant colors in the image.\n\n- Slider to choose between 3 and 12 colors to extract\n- Pixel-percentage shown for each color\n- Handles any image format the browser supports (PNG, JPEG, WebP, SVG, GIF)\n- Everything runs locally in the browser - the image never leaves your machine\n\n### 🧪 Color mixer\n\nBlend two colors in your choice of color space:\n\n- **RGB** - linear interpolation, classic CSS-style blending\n- **HSL** - hue-wheel interpolation (shortest path)\n- **OKLCH** *(default)* - perceptually uniform blending, gives visually balanced results (yellow + blue = teal, not muddy gray)\n\nPlus six post-blend effects: **tint** (lighten), **shade** (darken), **saturate**, **desaturate**, **warm**, **cool** - each with its own intensity slider.\n\n### 🌈 Color harmonies\n\nGiven a base color, generate six classic harmony types using OKLCH hue rotation:\n\n- **Complementary** (180° opposite)\n- **Analogous** (±30° neighbors)\n- **Triadic** (120° and 240°)\n- **Split-complementary** (150° and 210°)\n- **Tetradic** (90°, 180°, 270°)\n- **Monochromatic** (5 lightness variations with chroma compensation)\n\nBecause rotations happen in OKLCH (not HSL), harmonies stay perceptually balanced - a 60° rotation produces a shift of equal visual magnitude whatever the starting color.\n\n### 📏 Gradient builder\n\nA visual editor for CSS gradients:\n\n- Linear, Radial, or Conic types\n- Draggable color stops on a preview band\n- Click anywhere on the track to insert a new stop (color interpolated via OKLCH)\n- Per-stop hex + position inputs\n- Angle slider for linear/conic\n- Live CSS output ready to copy\n\n### 💾 History \u0026 export\n\nYour last 24 unique picks persist across sessions. The palette can be exported as:\n\n- **JSON** - full data with hex, RGB, HSL, timestamps\n- **CSS** - `:root { --color-01: #...; }` custom properties\n- **Figma** - W3C Design Tokens format (imports via the Tokens Studio plugin)\n- **Tailwind** - drop-in `tailwind.config.js` snippet\n\n### 🌍 Multi-language UI\n\nChromapicker auto-detects your browser's UI language on install and displays the interface in your preferred language. Currently supported:\n\n- **English** (default, fallback)\n- **French** (français)\n- **Portuguese** (português)\n- **German** (deutsch)\n\nStrings live in `_locales/\u003clang\u003e/messages.json` - a translation consists of a single JSON file. Contributions for additional languages are welcome via pull request.\n\n---\n\n## Installation\n\n### From the browser store\n\nhttps://chromewebstore.google.com/detail/chromapicker-color-picker/glhdgidjphkmhkfggpjalehpopngbkge\n\n### Manual install (developer mode)\n\n1. Download the latest release from [Releases](https://github.com/mthcht/chromapicker/releases) (or clone this repo)\n2. Unzip the archive\n3. Open `edge://extensions` or `chrome://extensions`\n4. Enable **Developer mode** (toggle in top-right)\n5. Click **Load unpacked** and select the unzipped folder\n6. Pin the icon from the extensions menu\n\nA welcome page will open on first install with visual instructions for pinning.\n\n---\n\n## Usage\n\n### Keyboard shortcut\n\n**Alt+P** triggers the picker from anywhere, without opening the popup. The hex is automatically copied to your clipboard and a confirmation toast appears on the page.\n\nYou can rebind this shortcut at `edge://extensions/shortcuts` or `chrome://extensions/shortcuts`.\n\n### Copy behavior\n\n- Clicking any HEX/RGB/HSL row in the popup copies that value\n- Clicking a history swatch copies its hex and promotes it as the current color\n- The **Copy all** button in Extract/Harmony sheets copies every color as newline-separated hex codes\n\n### Keyboard shortcuts inside the popup\n\n- **Esc** - close the currently-open sheet (Mix, Harmony, Gradient, Export, etc.)\n\n---\n\n## Permissions explained\n\nChromapicker requests only the minimum permissions needed to function. Here's what each one does and why:\n\n| Permission | What it does | Why Chromapicker needs it |\n|---|---|---|\n| **`storage`** | Read/write small amounts of data in the browser's local storage | Persist your color history (last 24 picks) and your latest pick between sessions. Nothing is synced to any server. |\n| **`clipboardWrite`** | Write text to the clipboard | Auto-copy a picked hex code so you can paste it directly into your editor without an extra click. |\n| **`scripting`** | Inject small scripts into the current tab | Required for the **Extract page** feature (walks DOM to collect colors), the **Highlight** feature (outlines elements using a given color), and the **Alt+P** shortcut (triggers the EyeDropper from outside the popup). |\n| **`activeTab`** | Temporary access to the tab you're currently on, only while you trigger an action | Lets Chromapicker operate on the current page without needing broad host permissions like `\u003call_urls\u003e`. No access to any tab you're not actively using. |\n\n**Chromapicker requests NO access to:**\n\n- Browsing history\n- Cookies\n- Passwords or form data\n- Network requests\n- Tabs other than the active one\n- Downloads, bookmarks, or extensions\n- Host permissions (no access to all URLs, no background page scraping)\n\nThe `commands` entry in the manifest registers the `Alt+P` shortcut - it's not a permission, just a keyboard binding.\n\n---\n\n## Privacy\n\n**No data leaves your browser. Ever.**\n\n- No telemetry, no analytics, no crash reports\n- No external network requests by the extension (Google Fonts loads the Noto Sans JP font from a CDN for the popup UI only - the extension itself never contacts any server)\n- No account, no sign-in, no cloud sync\n- Your color history lives in `chrome.storage.local` and is wiped if you uninstall the extension\n- Image palette extraction runs entirely locally using the Canvas API - uploaded images never leave the page\n\nIf you care about the Google Fonts request specifically, you can self-host the font by replacing the `\u003clink\u003e` in `popup.html` with a bundled `@font-face` declaration.\n\n---\n\n## Technical notes\n\n### Color picker implementation\n\nChromapicker uses the browser's native [EyeDropper API](https://developer.mozilla.org/en-US/docs/Web/API/EyeDropper), available in Chromium 95+. This reads pixels directly from the browser's compositor, giving perfect alignment with the cursor regardless of OS display scaling.\n\nAn earlier version attempted a custom picker using `chrome.tabs.captureVisibleTab` + a canvas-based magnifier. It was rejected because screenshot-based picking introduces sub-pixel offset issues on non-integer display scaling (125%, 150%) that can't be fully compensated for with math alone.\n\n### Color math\n\n- **OKLab / OKLCH** conversions use Björn Ottosson's [2020 coefficients](https://bottosson.github.io/posts/oklab/). Round-trip accuracy verified for the full sRGB cube.\n- **Harmony rotations** happen in OKLCH polar form so a 60° hue shift is perceptually consistent regardless of starting hue.\n- **Mixing** in OKLab beats naïve RGB for perceptual smoothness (the classic yellow+blue test produces teal, not mud).\n- **Image palette extraction** uses k-means++ seeding for stable cluster initialization, with 12 iterations cap for responsiveness. Pixels are downsampled to a max of 200px on the longest side before clustering.\n\n### Why OKLCH instead of HSL\n\nHSL's lightness channel is not perceptually uniform - `hsl(60, 100%, 50%)` (yellow) and `hsl(240, 100%, 50%)` (blue) look wildly different in brightness despite having the same L value. OKLCH corrects this and is the color space the CSS Color Module Level 4 spec uses as its reference. Modern design systems (Tailwind 4, Radix UI, Panda CSS) use OKLCH internally.\n\n### Wide-gamut (P3) detection\n\nThe hero badge row includes a **gamut indicator** that combines two signals:\n\n1. **Display capability** - `window.matchMedia('(color-gamut: p3)')` / `rec2020`\n2. **Page authoring** - scans all accessible stylesheets for wide-gamut color functions (`color(display-p3 ...)`, `color(rec2020 ...)`, `oklch()`, `oklab()`, `lab()`, `lch()`) plus inline `style=\"\"` attributes\n\nThe badge shows four states:\n\n- **P3** (green) - Page uses wide-gamut colors AND display can show them\n- **sRGB \\*** (amber) - Page uses wide-gamut colors but display clips to sRGB\n- **sRGB** - Classic sRGB everywhere\n\nThe native `EyeDropper` API always returns sRGB-clamped pixels, so picked colors can't recover wide-gamut data that was already thrown away - but the indicator tells you when the page is authoring wide-gamut content you might want to inspect with dev tools instead.\n\n### Browser support\n\n- Chromium 95+ (for EyeDropper API)\n- Manifest V3\n- No build step - plain ES2020 JavaScript, CSS, and HTML\n\n---\n\n## Development\n\n### Project structure\n\n```\nchromapicker/\n├── manifest.json          Extension manifest (MV3)\n├── popup.html             Toolbar popup UI\n├── popup.css              All popup styles\n├── popup.js               Popup logic: picker, mixer, harmony, gradient, export\n├── background.js          Service worker: install, keyboard shortcut, injection orchestrator\n├── welcome.html           First-install onboarding page\n├── icons/                 Extension icons (16/32/48/128 px)\n└── README.md              (You're reading it)\n```\n\n### No build system\n\nChromapicker is deliberately build-less. Edit the source files, reload the extension in `edge://extensions` or `chrome://extensions`, and you're testing. Keep it simple.\n\n### Testing locally\n\n1. Make your changes\n2. In the extensions page, click the **Reload** icon on the Chromapicker card (or click **Load unpacked** again)\n3. Open the popup to see changes - right-click **Inspect** if you need DevTools\n4. For background script changes, also click the **Service worker** link under the extension to inspect it\n\n### Contributing\n\nBug reports and feature suggestions are welcome via [Issues](https://github.com/mthcht/chromapicker/issues).\n\nFor code contributions:\n\n1. Fork the repo\n2. Create a feature branch\n3. Test in at least Chrome and Edge\n4. Open a pull request describing the change\n\nIf you're adding a new color space conversion or a new mixer effect, please include a round-trip / reference-value test in the PR description so the math can be verified.\n\n---\n\n## License\n\nMIT - do whatever you want. See [LICENSE](./LICENSE) for the full text.\n\n---\n\n## Credits\n\n- Built by [mthcht](https://github.com/mthcht)\n- Color math based on [Björn Ottosson's OKLab](https://bottosson.github.io/posts/oklab/)\n- Typography: [Noto Sans JP](https://fonts.google.com/noto/specimen/Noto+Sans+JP) via Google Fonts\n- Inspired by [ColorZilla](https://www.colorzilla.com/) - the classic color picker that set the bar\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmthcht%2Fchromapicker","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmthcht%2Fchromapicker","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmthcht%2Fchromapicker/lists"}