Capturing Dark Mode and Theme Variants Reliably

Capturing Dark Mode and Theme Variants Reliably

author

Snapshot Site Team

25 May 2026 - 03 Mins read

Dark mode is no longer a nice-to-have. It's a default expectation for a growing share of users, and that creates a real capture problem: if you only ever screenshot the light theme, you're not actually showing what a large chunk of your audience sees.

This shows up in a few recurring situations:

  • Marketing screenshots. Product pages and app store listings increasingly show both light and dark variants side by side, because buyers want to know the dark theme isn't an afterthought.
  • Visual regression testing. If your CSS pipeline supports both themes, your test coverage needs to as well. A regression that only breaks in dark mode is still a regression.
  • Documentation and support. A screenshot in a help article is useless if it doesn't match what the user is actually looking at. Half your readers are probably in dark mode already.

The problem is that there's no universal, automatic way to ask a screenshot tool for "the dark version" of a page. Every site implements theming differently, and a general-purpose capture API has no way to know in advance which one yours uses.

There Is No Built-In Theme Switch

It's worth being direct about this: Snapshot Site does not have a theme or colorScheme parameter, and it doesn't emulate prefers-color-scheme for you. If you're looking for a single flag that flips a page into dark mode, it doesn't exist here, and honestly it wouldn't work reliably even if it did — because dark mode isn't a browser-level feature you can universally toggle from the outside. It's application logic that lives in each site's own JavaScript and CSS.

What Snapshot Site does give you is javascriptCode, which runs arbitrary custom JavaScript in the page before the screenshot is taken. That's the actual mechanism for forcing a theme variant, and it works because most dark mode implementations boil down to one of a small number of patterns.

How Sites Actually Implement Dark Mode

Before you can force a theme, you need to know how the target site switches into it. In practice, it's almost always one of these:

  • A class or attribute on <html> or <body>. Something like document.documentElement.classList.add('dark') or a data-theme="dark" attribute that CSS selectors key off of.
  • A localStorage value read on page load. The site checks localStorage.getItem('theme') (or similar) during initialization and applies the theme accordingly.
  • A system preference check. The site defaults to prefers-color-scheme but then lets a toggle button override it, usually by writing to one of the two mechanisms above.

The fastest way to find out which one applies is to open the target site yourself, inspect the theme toggle button, and look at its onclick handler or the click listener attached to it in the dev tools sources panel. You're looking for the exact class name, attribute, or storage key it flips.

Replicating the Toggle With javascriptCode

Once you know the mechanism, you replicate it directly in javascriptCode. A few examples depending on what you find:

  • Class-based theming: document.documentElement.classList.add('dark');
  • Data-attribute theming: document.documentElement.setAttribute('data-theme', 'dark');
  • LocalStorage-based theming: localStorage.setItem('theme', 'dark'); location.reload();

That last case is the trickiest one. Some sites only read localStorage once, on initial load, so setting the key alone won't repaint an already-rendered page — you need to trigger the site's own re-render logic, whether that's a full reload, a call to whatever function the toggle button invokes, or dispatching a custom event the site listens for. This is exactly why there's no universal one-liner: the correct script depends entirely on how that specific site was built, and it takes a few minutes of inspection per site to get right.

Don't Skip the Delay

Once the theme change fires, give it time to actually finish rendering. Most dark mode implementations animate the swap with a CSS transition on background and text colors, and capturing mid-transition produces a washed-out, half-toned screenshot that looks broken rather than dark.

Pair your javascriptCode with a short delay — even one or two seconds is usually enough — so the transition settles before the frame is captured. If the site also lazy-loads theme-dependent assets (icons, illustrations, syntax-highlighting themes), a slightly longer delay is worth the extra second of wait.

Set Expectations Accordingly

This isn't a one-line switch, and it shouldn't be treated as one. Every site's theming implementation is different, which means every site needs its own small investigation before you can script it reliably. But once you've identified the mechanism, forcing a specific theme variant with javascriptCode and delay is straightforward, repeatable, and works for one-off marketing shots just as well as it does for a full visual regression suite that needs to run against both themes on every deploy.

If you're building out dark mode coverage across a real test suite or a documentation pipeline, Snapshot Site gives you the capture primitives to do exactly that.

Recent Articles

How to Screenshot a WordPress Site in PHP

How to Screenshot a WordPress Site in PHP

A practical guide to capturing WordPress pages and posts from PHP, including handling cookie banners, cached pages, and full-page content captures....

- 02 Mins read

Subscribe to Snapshot Site API

Snapshot Site is a powerful API that allows you to capture full-page, high-resolution screenshots of any website with pixel-perfect accuracy.
Simply send a URL to the API to generate a complete snapshot — not just the visible area — covering entire web pages, scrolling content, landing pages, blogs, news articles, social media posts, videos, and more.
Designed for developers, designers, marketers, and journalists,
Snapshot Site makes it easy to integrate web page capture into your applications, workflows, and automation tools.

Subscribe Now
bg wave