In short: every color on the page becomes a CSS variable, and a new palette rewrites the variables
How Recolor repaints a page
Recolor (recolor.page) works in three moves: it fetches a page through its own Worker, shows it in a sandboxed frame and rewrites every color the page uses into a CSS variable that still holds the original. A new palette then changes only those variables, in one write, so the page repaints a few milliseconds after you press Space.
Last updated
src/worker, src/engine, src/shared/mapping.ts), checked October 8, 2026| Step | What happens | Where |
|---|---|---|
| 1. Fetch | The Worker fetches the page (up to 5 MB), puts its stylesheets inline and adds the engine script | Cloudflare Worker |
| 2. Show | The app puts the prepared page in a sandboxed frame: its scripts may run, but cannot reach Recolor | Your browser |
| 3. Read | The engine reads every color in the stylesheets, inline styles and SVG attributes, and weighs how much of the page each covers | The page |
| 4. Rewrite | Each exact color becomes its own CSS variable, set to the original, so the page looks unchanged | The page |
| 5. Group | Colors within 0.04 in OKLab form a cluster; clusters within 25 degrees of hue form a family | The page and the app |
| 6. Map | Families take swatches by rank, greys take a tint of swatch 1, text keeps its contrast | The app |
| 7. Repaint | One write sets every variable; the browser restyles the page | The page |
Three parts: the app, the Worker and the engine
The app is what you see: the toolbar, the preview and the palette strip. It generates palettes, keeps history, and works out which palette color each page color becomes.
The Worker runs on Cloudflare under the same address as the app. It fetches the page you asked for, puts every stylesheet it can fetch inline, rewrites relative addresses so images and fonts still load, and adds two scripts at the top of the page: a small configuration and the engine. With the Scripts switch off it also removes the page's own scripts. What it fetches, and what it never keeps, is on What Recolor stores and fetches.
The engine is a 59.3 KB script that runs inside the previewed page. It reads the page's colors, rewrites them into variables, reports what it found to the app, and applies each new palette.
The preview is an iframe with sandbox="allow-scripts" and the page in its srcdoc. The page's scripts can
run, but the frame has no origin of its own, so they cannot read Recolor's storage, open windows or submit forms.
The engine and the app talk only through messages.
What happens when a page loads
The engine starts when the page's HTML has been parsed. It walks every stylesheet it can read, including media
queries, layers, container queries, nested rules, keyframes and imports, plus inline styles and the colors SVG
and old HTML set by attribute (fill, stroke, stop-color, bgcolor and the like). For each color it
counts how many elements the rule reaches, and gives backgrounds extra weight by their area, so the color of a
hero outweighs the color of a hairline border.
Every exact color gets its own CSS variable, such as --rc-c3m1, and every declaration that used it is rewritten
to point at that variable. The variables start at the page's own values, in its own notation, so before a palette
arrives the page keeps its look: with scripts off, on all 16 sites tested on
October 8, 2026, no computed color moved by more than 0.02 in OKLab, too little to see. Colors closer
than 0.04 in OKLab are reported
as one cluster, which is what the app ranks and what the Site colours panel lists.
The engine also notes which text sits on which background, so the mapping can keep it readable, and it keeps watching: rules and elements that scripts add later are read in batches 100 ms after they appear. The status line then shows what it found, for example "26 colours, 1 sheet, 22 ms". How long that takes on real sites is on Which sites load; the size limits are on Limits.
What happens when you press Space
Space generates a new palette in the app: a color scheme, a ladder of lightness from dark to light, and neighbors kept at least 0.08 apart in OKLab. Locked colors stay. The app then maps the page:
- Chromatic clusters within 25 degrees of hue form a family, so a brand's shades, its hover color and the stops of its gradient move together.
- Families are ranked by weight times chroma; the first takes swatch 1, the second swatch 2, and so on.
- Each color moves towards its swatch by the Strength setting, 70% by default, and large shifts in lightness are held back, so a dark section stays dark.
- Greys keep their lightness and take a tint of swatch 1 by the Neutral tint setting.
- Text is checked against what it sits on and given back lightness until it reads at least as well as before, up to 4.5:1.
The result is a list of variables, posted to the engine and written into the page as one style element. On October 7, 2026 the production build wrote it 3 ms after the key (the median), and on 8 or 9 of 20 presses the page repainted in the same frame as the strip, one frame later otherwise. The mapping itself takes 2 to 4 ms even on github.com, whose page has 1,012 distinct colors. The details and the settings are on Strength, neutral tint and overrides, and the reasoning about lightness on why a dark hero stays dark.
What it cannot repaint
Images, video, canvas and WebGL keep their colors: they are pixels, not CSS. A photo, a logo saved as PNG or a hero drawn in WebGL stays as it is; the Grey images switch in the Mapping panel greys them out so the palette reads on its own. Shadow DOM that a script attaches is not read.
A stylesheet the engine cannot read, because the Worker could not fetch it, is handled element by element: the engine sets the new colors on each element directly. The page still repaints, but hover colors from that sheet keep their originals. The same technique, applied by hand to a site you own, is in How to recolor a website with CSS variables.
Common questions
Does Recolor change the website itself?
No. It repaints a copy of the page in your browser. The site, its files and its visitors never see the palette.
Does the page keep working while it is recolored?
Yes, mostly. Links on a page loaded from an address open through Recolor, forms are cancelled, and with the Scripts switch on the page's own scripts run, though scripts other sites load as modules often cannot start in the sandbox.
Does Recolor use AI to pick the colors?
No. Palettes come from color schemes and a lightness ladder in OKLCH, and the mapping follows fixed rules: rank by weight, hue families within 25 degrees, a lightness guard and a contrast check.
Can Recolor recolor images and video?
No. Images, video, canvas and WebGL keep their colors. The Grey images switch shows them in grey so they do not distract from the palette.
Is the repaint instant on large pages?
Yes, as far as the eye goes. The mapping takes 2 to 4 ms; the browser's restyle afterwards is what grows with the page, 1 to 3 frames after the strip on github.com, with 28,104 declarations.
Does a page pass through a server?
Yes. A page from an address is fetched by Recolor's Worker on Cloudflare, and an uploaded file is sent there to be prepared. Uploads are never stored or cached; a fetched page is cached for 60 seconds.
Sources
- The iframe element and its sandbox attribute, MDN developer.mozilla.org
- Using CSS custom properties, MDN developer.mozilla.org
- CSSStyleDeclaration: setProperty(), MDN developer.mozilla.org
- MutationObserver, MDN developer.mozilla.org
- HTMLRewriter, Cloudflare Workers docs developers.cloudflare.com