Hacker News new | past | comments | ask | show | jobs | submit login

At Brex, we released an experimental dark mode for our dashboard a while ago using these 4 lines of global CSS:

  body {
    background-color: black;
    filter: hue-rotate(180deg) invert(90%);
  }
We tweeted a video showing what it looks like here: https://twitter.com/derekstavis/status/1306365758411161605

A lot of customers were asking for it, but we weren't going to be able to implement it properly anytime soon, so this was the hacky compromise we came up with to deliver value as quickly as possible.

This has a bunch of edge cases you'll likely have to deal with case by case by applying the inverse filter `filter: invert(111%) hue-rotate(180deg);` selectively, but for us it actually worked shockingly well for the most part.

I suspect it will work best on the typical app design where most things are different shades of gray, and probably not as well on sites with backgrounds composed of non-gray hues (like right here on hacker news: https://imgur.com/a/jITAn6x) or apps with tons of user-generated videos/images.

If that fits the description of your app, I'd encourage you to give it a try, and maybe even ship it to customers (like we did) if it looks good enough! (I'd personally love to see some screenshots if you decide to do this!)

And of course, we're hiring: https://www.brex.com/careers/ ;)




An invert-rotate approach to a dark mode works great until you have any sort of layering (i.e. modals). This is where it really falls apart. Shadows become glows, and make it much harder to differentiate between layers.

If you're going for a quick hack like the above code, I'd recommend at least separating out your shadow styles into a css variable. I.e.

    :root {
      --shadow-color: #000;
    }

    .modal {
      box-shadow: 0 0 8px var(--shadow-color);
    }

    @media (prefers-color-scheme: dark) {
      :root {
        --shadow-color: #fff;
      }
      html {
        filter: hue-rotate(180deg) invert(1);
      }
    }


Thanks for the call out. I took a look at the modals in our dashboard and by default they have a super-subtle, barely visible shadow on top of an overlay, which looked fine.

I exaggerated the shadow a lot and this is what it ended up looking like: https://imgur.com/a/ustLofp

Definitely not pretty, but also probably not the end of the world. I can see this becoming problematic if we have more than a single additional layer, but we generally try to keep layering to a minimum so it hasn't been a problem for us yet.

Definitely something for folks looking to try this to keep in mind though.


This is a good corner cut, but in addition to other comments, there's two huge accessibility concerns, and one usability/design principle problem:

1. The color spaces available in CSS are not perceptually uniform. You may achieve some a11y checkbox with the inversion of luminosity/hue, but that doesn't mean it's actually readable.

2. Not all, but many, dark mode users prefer lower contrast in some areas to reduce brightness over all. This approach can tailor in the opposite direction.

3. In general with dark themes, it's still generally preferable for darker-in-light-mode things to be darker in dark mode. This does the opposite and can lead to confusing design structure.


These are all great points for anyone looking to try this to keep in mind.

For us, on points 1 and 2, we have done some due diligence on going through all the different pages/flows on our dashboard to make sure everything still looks good and text remains readable. A lot of folks internally prefer dark mode and dogfood it day to day which also helps a lot. So far we also haven't heard any major complaints re: readability/contrast from our customers, thankfully, but of course as soon as we do, we'll adjust and re-evaluate.

On point 3, this is where the inverse filter trick comes in handy, we've had to apply this in a few places where the inversion made things look awkward and/or unusable, most notably external partner logos and user-uploaded receipt pictures.

All of this is part of why it's still labeled as an experimental feature even months after release.


I’m super curious how much effort has gone into evaluating what works and making adjustments. I’m not trying to poo poo the idea if it’s working and doesn’t have a noticeable performance impact.

I know when I came back to web dev a year ago after five years fully backend this is exactly the idea I wanted to try. I asked the advice of a friend who’d stayed FE as dark mode rolled out and he said, basically it’s more trouble than it’s worth. I took that advice and built a dedicated dark mode for the project at that time. And I did so for my personal site which is a fairly intricate labor of design love (link in profile).

Honestly it was hardly any additional effort, and it wasn’t an afterthought. I prefer light mode generally but I like my own site’s dark mode better almost across the board. But there were so many details that I think would have been more work, and probably more difficult work, if I tried to start with filters and adjust.

FWIW, I don’t use it throughout but I do use it where I wanted programmatic control of color: I highly encourage looking at HSLuv or another perceptual color space to handle some of this.


The whole thing has been fairly hands-off for us, surprisingly enough, as I fully expected this to be a maintenance nightmare that we might have to pull back, hence the experimental label. I could count on a single hand the number of times we had to make adjustments since we shipped it.

I'd honestly love to be able to implement dark mode the proper way with semantic color tokens and runtime theme swapping someday. But since our codebase didn't start with hot-swappable theming in mind, retrofitting a proper theme-based dark mode into it would be a gigantic undertaking that we'd have trouble justifying against all of our other priorities.

For anyone building a brand new app, definitely start by implementing themes the right way instead of using this hack. You'll definitely save yourself a lot of headache down the line.


> But since our codebase didn't start with hot-swappable theming in mind

But it doesn’t have to be that thought out. It just needs the same kind of symmetry you’ve applied, wherever you’ve applied colors (and maybe lighten font weight a bit). You can just use a media query and target the same selectors.


There's probably this too: https://darkmodejs.learn.uno/


This certainly looks better than the one in the article!




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: