EclipseModeAll guides
How it works

How dark mode extensions actually work

Last updated: 20 August 2026 · By the Eclipse team — we build one of these, so the architectural detail here is first-hand rather than inferred.

The short answer: there are three approaches, and almost every complaint about dark mode extensions traces back to which one you are running. A CSS filter is fast, universal, and wrecks your photographs. Stylesheet rewriting is more precise and breaks on dynamic pages. A generated theme looks best and costs the most work. Knowing which machine you have explains the quirks you have been putting up with.

Approach 1: the CSS filter

Apply a filter to the root element and the whole page transforms at once — typically an inversion, often with a hue rotation to undo the worst of the colour damage.

Why it is appealing: it runs in the browser’s compositor, costs almost nothing, works on literally any page including ones that have not loaded yet, and cannot be defeated by a site’s CSS structure.

Why it disappoints: it operates on rendered pixels, after all meaning has been discarded. It cannot tell a background from a photograph. Full explanation of why inversion is not dark mode.

Approach 2: stylesheet rewriting

Walk the page’s stylesheets, find declarations that set colours, and substitute darker values. More surgical: you know a value came from background-color, so you know it is a surface.

Where it struggles: modern pages do not keep their colours in tidy stylesheets. Colours arrive via inline styles, CSS custom properties resolved at runtime, styles injected by JavaScript, and shadow DOM with its own encapsulated rules. Cross-origin stylesheets may not be readable at all. Rewriting has to chase all of that continuously, and every element added after load needs handling again.

Approach 3: generated themes

Collect the page’s colours, classify each by role, transform each according to its role, and emit a new stylesheet. This is what the better extensions do by default, and it is what Eclipse does.

The pipeline, concretely:

  1. Collect declared colours from stylesheets and computed styles.
  2. Classify each as surface, text, border, accent, shadow or gradient. This is the step that makes everything downstream possible.
  3. Transform in a perceptual colour space — Eclipse uses OKLab — compressing surface lightness while preserving hue, and damping chroma because saturated colours read as more intense against dark backgrounds.
  4. Solve text contrast against each text colour’s actual new background, using APCA rather than a fixed palette — why that model, not WCAG’s ratio.
  5. Gamut-map results back into what the display can actually show.
  6. Emit the generated rules as a stylesheet the browser applies.
  7. Watch for DOM changes and repeat incrementally for new content.

The two hard problems

1. Doing it before the page paints

If your styles arrive after the browser has started painting, the user sees the original light page first — the white flash. Avoiding it means the styles must exist before the page runs, which rules out computing a bespoke theme on the fly for the first paint.

Eclipse resolves this by pre-generating CSS for each preset at build time and registering it to run at document start, so the dark styles are already in place when the page paints. The fully analysed per-site theme is layered on afterwards. It is a real constraint — you trade some flexibility for never flashing — and there is an automated test that records frames during load and fails the build if a light frame appears.

2. Keeping up with a page that will not sit still

A social feed can fire thousands of DOM mutations while you scroll. Reacting to each one individually is how an extension ends up measurably slowing the browser down. The mitigations are coalescing mutations into batches rather than handling them one at a time, and memoising colour transforms keyed on the input colour, its role and the active theme — the same handful of brand colours recur thousands of times per page, so a bounded cache turns most of the work into a lookup.

Where all three approaches fail

Some content is unreachable regardless of technique: pixels drawn inside a <canvas>, cross-origin iframes, colours baked into images, and video. These are browser security and architecture boundaries, not bugs — the full list is here.

What this means when choosing one

Symptom you dislikeWhat it tells you
Photos look like negativesYou are on a filter mode
Browser slows over a sessionMutation handling or unbounded caches
White flash between pagesStyles applied after paint begins
Text hard to read on darkContrast model, not brightness
Parts of a page stay lightCanvas, iframe or shadow DOM boundary

Try it yourself: Eclipse applies a generated dark theme to any site, with per-site overrides and live brightness and contrast controls. Free, no account, no site limits.

Related guides

Why Inverting Colours Isn’t Dark Mode
Inversion flips your brand blues to orange and your photographs to negatives. What a real generated theme does differently, in colour-space terms.

Why Dark Mode Flashes White — and How to Stop It
That stab of white between page loads is a race condition, not a bug in your eyes. What causes it, why it is hard to fix, and what a fix requires.

Dark Mode Not Working on Some Sites? 9 Causes
Shadow DOM, canvas, iframes, inline styles, CSP — the specific technical reasons a page resists dark mode, and which ones are actually fixable.

What Dark Mode Extensions Can See
Restyling a page requires reading it. That is a real permission with real implications — here is how to audit any extension before trusting it.

Browse all 16 guides →

© 2026 Eclipse. Not affiliated with Google, Chrome, or any website we write about.
HomeGuidesPrivacyTermsChangelog