Laziest Possible Dark-Mode Toggle - Using :has() and invert()


I'm not saying this is a good way to make a dark mode website. I'm not even saying it's a sensible way to do dark mode. But I'm pretty sure this is the laziest way of getting dark mode on your site. And it is all done with less than a handful of CSS rules.

It relies on the new-ish :has() CSS pseudo class and the positively ancient filter() CSS function.

Here's the code in all its glory:

body:has( > #dark-mode-checkbox:checked ) {
  filter: invert(1);
  background: #000;
}

#dark-mode-checkbox:checked ~ img {
  filter: invert(1);
}

That does three things. If the body has an <input id="dark-mode-checkbox" type="checkbox"> which is selected, then:

  • Invert all the colours on everything on the site.
  • Manually set the background of the body, because the above is only filtering the descendants of the body.
  • Find any images and invert them, so they're the right colour.

Here's some minimum viable HTML:

<body>
  <input id="dark-mode-checkbox" type="checkbox">
  <label class="dark-mode-label" for="dark-mode-checkbox">Enable dark mode</label>
  <h1>Heading</h1>
  <p>Test</p>
  <img src="https://placekitten.com/128/128" alt="A cute kitten">
</body>

Demo

You can play with the demo.

It should look like this:
A light website with a photo of a kitten.A dark website with a photo of a kitten.

Caveat

A few issues:

  1. This doesn't yet work on Firefox. Even if you enable layout.css.has-selector.enabled in about:config. Support is coming soon™.
  2. Inverting colours isn't the same as a properly designed dark mode. You absolutely shouldn't use this in production.
  3. There are no accessibility guarantees. Please test this before subjecting your users to it.
  4. This doesn't remember your user's choice. So they'll need to toggle it on every page load.
  5. Who knows what eldritch horrors this will unleash upon humanity.

Share this post on…

3 thoughts on “Laziest Possible Dark-Mode Toggle - Using :has() and invert()”

  1. Instead of a checkbox, you could be even lazier and use the prefers-color-scheme media query:
    @media (prefers-color-scheme: dark) { ... }

    Reply
    1. @edent says:

      Yes. But that doesn't allow for a user to change the setting on a per-page basis.

      Reply

What links here from around this blog?

What are your reckons?

All comments are moderated and may not be published immediately. Your email address will not be published.Allowed HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <p> <pre> <br> <img src="" alt="" title="" srcset="">