* Some diagrams had white backgrounds
Solution: remove the backgrounds so they are transparent
* Most diagrams had black lines/arrows which didn't look good on dark gray backgrounds
Solution: use CSS filter:invert for images
* Some images are photos not diagrams so inverting their colors doesn't work
Solution: Use a selector for svg only img[src$=.svg] and a class when manually needed
* Some svg diagrams have their colors referred to like "see the red object" in that text.
Solution: filter: invert(1) hue-rotate(180deg);
That makes the blacks become white but the colors kind of stay the same hues at least
* The are many interactive digrams on the sites.
Solution: All of those had to be refactored to not use hard coded colors but do something like
const darkMatcher = window.matchMedia("(prefers-color-scheme: dark)");
const isDarkMode = darkMatcher.matches;
const colors = isDarkMode ? darkColors : lightColors;
And draw everything with the appropriate colors. Its up to you if you want to trigger re-drawing if the user changes their preference* Some text was color coded for to match the diagrams as in
<span style="color: red;">x-axis"</span>
But now those colors looked bad on a dark background.Even 5 months later I still find places I missed.
(It doesn't seem to have occurred to that author to try reducing the brightness of the images, or reducing saturation with the saturate() instead of grayscale(), but those also seem worth trying, brightness in particular.)
Apple's Smart Invert is even simpler, it just leaves media like images and video as-is, only inverting colors of other things.
I suppose for diagrams that you know are black-on-white, inversion is nice, but it should be opt-in.
> Solution: filter: invert(1) hue-rotate(180deg);
This might be nominally acceptable, but it’s going to be pretty mediocre. Both of these methods dramatically distort color relationships from the original.
Getting someone to explicitly pick colors that work in dark mode will yield much better results. (Of course, takes a lot more manual work by an expert, instead of a few automatic text replacements.)
Some people prefer dark mode because they suffer migraines and bright lights are a problem when they have a migraine. Or homeless people may be using it for both stealth purposes and battery conservation when they have limited opportunities to recharge.
For some people, this preference is not just some minor detail. It's a much more important thing than "I just happen to like dark color schemes."
You'd never define a particular color, just algorithms for taking some input color and deriving each needed color from that one.
Then the user can say: "I want this file in blue and this one in orange" and the syntax highlighting still calls out the features in a relative way but the absolute colors are used as cues for something else (like test coverage or something from source control).
Ok, maybe doing UI's would be fun after all.
This sucks when you want then share the diagram with someone, on certain platforms the diagram will be unreadable due to the lack of contrasting background.
- 2 device sizes: desktop vs mobile (e.g. responsive)
- 3 platforms: web vs iOS vs Android, or web vs Windows vs macOS vs Linux (not even counting cross-browser or OS version quirks), or god forbid all of the above
- 2 input methods: hover/click/drag vs tap/hold/swipe
- 2 modes for accessibility: full visual+audio vs screenreader/captioned
- And now 2 visual modes: light vs dark
That's 48 combinations to design and test for. I'm probably forgetting some too. But as a developer it makes just the baseline cost of any basic app so damned high.
Again, as a user I love it. But the entrance cost for entrepreneurs, or even hobbyists? Man oh man.
Whenever people introduce any of those things, like when iOS was introduced, they had to decide how to port all the existing content and interactions and widgets to mobile and touch interfaces. As a result, if an entrepreneur or hobbyist makes an app on one platform and wants it to be at least minimally usable on another platform, the Web way, way lowers the barrier to make that jump.
In many ways, it's even worse. I've got OS settings here for "increase contrast", "reduce transparency", "use grayscale", "invert colors", and (because areas of native windows can be translucent) even the desktop wallpaper comes into play.
I turned on dark-mode for testing my own app, and I had to turn it off because there's parts of Xcode where the contrast ratio is less than 1.1:1.0. The text is downright invisible. Obviously nobody at Apple would ever intentionally make software like that. They must have simply never thought to test with the same settings as I have.
https://pbs.twimg.com/media/D1kfN6SUcAEwWxq?format=png&name=...
Only problem - that is not what the market wants. Client: "why did you not implement the scrollbar-hijack/moving-blinking-text!?!?"
And then imagine if your web site is multilingual...
Or use the same dark colors for mobile-size and desktop-size in responsive, but still need to test it to make sure I got all the <div>s that appear in mobile-size but get hidden and/or replaced by other <div>s in desktop-size and vice-versa.
Or discover we thought we'd covered everything, but when you use the normally-touch interface with a trackpad on Chromebooks, the default hover state is still light-mode.
Etc.
- content hierarchy (what's important on one platform will rarely change between other platforms, despite the developer guessing otherwise)
- interactivity (the platform can most of the time cater to the differences in input if you lean on the platform capabilities)
- style
- Iterate and Perfect on the 48 versions
If you want the user to be able to toggle dark mode on your site without changing their Operating System preferences, then you'll need to implement your dark theme as a class (eg. body.theme-dark) since there's no way to dynamically set the media query.
const darkMode = window.matchMedia('(prefers-color-scheme: dark)')
if (darkMode) {
document.body.classList.add('theme-dark')
}
If you have to write your dark theme CSS as a separate class, then there's no sense in duplicating that logic inside the media query and having to override it when the user toggles it. So I ended up using that Javascript instead of putting the styles in the media query.It's a shame, I would've preferred a pure HTML/CSS solution.
My suggestion of still using classes doesn't eliminate centralization of config, it just means moving the dark mode CSS outside of the media query and into a class, and adding a couple lines of Javascript.
For instance, the first version of Tweetbot for iOS 13 wouldn't allow you to choose a dark theme if iOS was set to use a light theme.
This was quite frustrating because I like Safari in light mode, but I like Tweetbot, iBooks, Kindle, etc in dark mode. This always has always worked and I'd see a different behaviour as a regression. That said Tweetbot fixed the issue very quickly (in a day).
There's normally a little more to it than that, but there shouldn't ever be _much_ more, custom properties are fully dynamic
Anyway, to accomplish this you would split your styles into seperate CSS files and then have a drop-down that does an HTTP POST/GET to a server side script that will then set a cookie on your browser with your preferred choice.
Each time a request comes in from the client you just check that cookie for which style they want and then change the HTML that's sent to include a different stylesheet.
Also I made a small mistake in the code there, it's `isDarkMode = window.matchMedia('(prefers-color-scheme: dark)').matches`
If we want to support dark mode now we have to support four different options. Writing that with a combination of classes and media queries is going to be a nightmare:
.default-theme h2 { background: white; color: black }
.inverted-theme h2 { background: black; color: white }
@media (prefers-color-scheme: dark) {
.default-theme h2 { background: black; color: white }
.inverted-theme h2 { background: white; color: black }
}
Your trick might make this a little more palatable.Sorry, I missed the "without changing their Operating System preferences". I agree with another sibling comment here: that seems like bad practice.
This is an interesting choice. While it might be easier on the eyes, personally it feels kind of icky to change colors on images…
By making everything on your site dark and low-contrast, the implication is that the user wants to see other things on the screen in higher contrast alongside your site, like the UI chrome. That seems unlikely - your site is the most important content that they have on the screen at that time and it should probably have the highest brightness or contrast of anything on the screen, not the lowest.
Though regular photos (and videos) are rarely so bright that it hurts the eyes while in a dark environment, unlike diagrams and other kinds of drawings, which can easily be mostly white.
Some people find these kinds of sites pointless these days, but I enjoy keeping one even if I rarely update it anymore. Spirit of the web and all that.
FWIW the Twitter feed from, I assume, people you follow is a little odd though - it's not immediately clear that it's not you, nor about the article being viewed, which it doesn't necessarily have anything to do with, and it includes replies to threads. At the time of writing the top one is recommended reading that's 'racist from the start'.
One of the upcoming posts is going to cover handling dark mode for <canvas> content. So far I've just used transparent backgrounds with no black or white drawing so that it's visible either way.
Not much on it yet, just been slowly working through the setup for doing a canvas with a responsive site.
Neat tidbit - the logo image is a single SVG in shades of dark gray, which doesn't work well on a dark background. You can apply image transformations in CSS under the dark mode media query to adapt things like this:
img#wi-logo {
filter: invert(100%) brightness(110%);
}
This is the same tool that the linked post uses for desaturating images, but adding that invert is a useful tool for dark mode. Personally I wouldn't recommend general image desaturation, photos taking more focus against a dark background is a good look if you ask me. At least consider making it an opt-in setting instead of the default.The logo design itself is really slick, though!
It defaults to the light version and then switches to the dark them on request.
This is so people who don't care or aren't good with computers get the light version and those that can set the system theme have the option of getting the dark version.
Or more importantly, people whose browsers/OSes don't set that CSS flag
I've used CSS variables though, which make it even simpler. E.g. I have `--page-background-color` and `--text-color-primary` that are set to a certain default value. In dark mode, these variables are set to other values, removing the need to redefine the actual selectors.
Works great.
document.body.style.filter = "invert(1)";
document.body.style.backgroundColor = "#141414";
I use a fine tuned custom stylesheet with Stylus chrome extension.https://github.com/darkreader/darkreader
https://github.com/openstyles/stylus (not built into release yet)
By the extension author's own admission [1], the majority of the revenue comes from the Safari extension, but he still prioritizes the (I imagine) larger user base of the firfox and chrome extensions. It's frustrating, to say the least.
[1] https://github.com/darkreader/darkreader/issues/1205#issueco...
I wrote about it here: https://carlschwan.eu/2019/07/12/new-userbase.html
I didn't do the "dimmer images" thing, but I'll try it sometimes.
I know some people would prefer a light-on-dark color scheme in general, even during the day. Is this entirely about what you see in the dark, or is there a component of wanting more "skins" in general?
https://medium.com/@mwichary/dark-theme-in-a-day-3518dde2955...
It's a testament to how primitive the web is as a platform that it can't do something like apply a universal theme like Windows 3 did.
Still not a complete replacement of global colour overriding (white flashes, or simply switching between dark and light themes often, can be quite unpleasant in a dark environment, and of course all the websites won't ever employ it, and some will use it wrong), but at least from the webmaster side it should simplify the colour theme decisions quite a bit (which were/are hard if you care about that sort of thing: I hoped that major web browsers will do something like that with alternate stylesheets someday, but as a media feature it would work too).
iOS at least does not. Perhaps because some sites customize foreground colors but not background colors or vice versa, and they’d break if the foreground wasn’t dark or the background wasn’t light.
I wrote about it at https://chrismorgan.info/blog/dark-theme-implementation/.
javascript:(function() { var tag = document.createElement('style'); tag.type = 'text/css'; document.getElementsByTagName('head')[0].appendChild(tag); tag[ (typeof document.body.style.WebkitAppearance=='string') ? 'innerText' : 'innerHTML'] = '* { background-color: white !important; color: #444 !important; } html { filter: invert(100%) grayscale(100%); }'; })();
This is such nonsense. Pure black is never pure black on a monitor and neither is white. And the link he provides just restates the assertion with no additional reasoning.
See, I get it. If you create work as an artistic statement, you deliberately pick not-quite-blacks/whites because the defaults are not your artistic choices if you just default to them.
However, once you take this as a given rule and you pick some not-quite-white because "it is recommended", that defeats the entire purpose.
The beauty of this setting is that it falls back 100% gracefully. Basically if your OS and/or browser doesn't support it, then you just see the "normal" version of the site.
Because Dark Mode is only available on newest versions of most operating systems, it is also reasonable to assume that the people running a dark mode compatible device would have a modern browser.
So all-in-all, I think compatibility is a moot issue.
I find it kind of ironic that there's so much debate surrounding the intricacies of dark mode support on a forum with no dark mode support (even though it avoids 90% of the gotchas).
I like working in Solarized Dark, so I wanted my website to serve up Solarized Dark. I dim images in dark mode too, but I turn them up to full brightness on hover.
Does that kind of CSS allows a script to determine if the browser is displaying dark mode or not, or send back that information to ads servers?
Don't get me wrong - I quite enjoy dark mode most of the time, but why now and not earlier?
https://android-developers.googleblog.com/2012/01/holo-every...
I’m guessing a few people finally decided to do it in other places.
I tested it a month ago and figured an update was coming soon. But I just tested it again on iOS 13.1 with everything up to date and still no luck. Safari works as my control.
yes yes there's browser plugins, but I'd rather not have some rando plugin potentially reading every site I visit to load a dark mode plugin on the ones it recognizes.