287

Similar to "How to detect if OS X is in dark mode?" only for browsers.

Has anyone found if there is a way to detect if the user's system is in the new OS X Dark Mode in Safari/Chrome/Firefox?

We would like to change our site's design to be dark-mode friendly based on the current operating mode.

Davy de Vries
  • 4,578
  • 2
  • 14
  • 29
funkju
  • 3,463
  • 2
  • 15
  • 19
  • 1
    As far as I know, there is no CSS media query for Safari to detect the light or dark mode, but Safari definitively supports dark widgets in HTML pages. It may be helpful to file a radar for it. – mschmidt Jun 13 '18 at 19:41
  • 1
    Don't hiurt me, but after [Stackoverflow introduced the dark mode](https://stackoverflow.blog/2020/03/30/introducing-dark-mode-for-stack-overflow/) I [googled](https://www.google.com/search?q=detect+dark+mode+in+html&oq=detect+dark+mode+in+html) how they implemented the "system" mode and stumbled upon this question. I expect a lot of traffic on this :-) – usr-local-ΕΨΗΕΛΩΝ Apr 01 '20 at 12:20
  • 1
    For CSS - `@media (prefers-color-scheme: dark) { }` – Jermaine Antwi Dec 31 '22 at 11:06

7 Answers7

366

The new standard is registered on W3C in Media Queries Level 5.

NOTE: currently only available in Safari Technology Preview Release 68

In case user preference is light:

/* Light mode */
@media (prefers-color-scheme: light) {
    body {
        background-color: white;
        color: black;
    }
}

In case user preference is dark:

/* Dark mode */
@media (prefers-color-scheme: dark) {
    body {
        background-color: black;
        color: white;
    }
}

There is also the option no-preference in case a user has no preference. But I recommend you just to use normal CSS in that case and cascade your CSS correctly.

EDIT (7 dec 2018):

In Safari Technology Preview Release 71 they announced a toggle switch in Safari to make testing easier. I also made a test page to see the browser behaviour.

If you have Safari Technology Preview Release 71 installed you can activate through:

Develop > Experimental Features > Dark Mode CSS Support

Then if you open the test page and open the element inspector you have a new icon to toggle Dark/Light mode.

toggle dark/light mode


EDIT (11 feb 2019): Apple ships in the new Safari 12.1 dark mode


EDIT (5 sep 2019): Currently 25% of the world can use dark mode CSS. Source: caniuse.com

Upcoming browsers:

  • iOS 13 ( I guess it will be shipped next week after Apple's Keynote)
  • EdgeHTML 76 (not sure when that will be shipped)

EDIT (5 nov 2019): Currently 74% of the world can use dark mode CSS. Source: caniuse.com


EDIT (3 Feb 2020): Microsoft Edge 79 supports dark mode. (released on 15 Jan 2020)

My suggestion would be: that you should consider implementing dark mode because most of the users can use it now (for night-time users of your site).

Note: All major browsers are supporting dark mode now, except: IE, Edge


EDIT (19 Nov 2020): Currently 88% of the world can use dark mode CSS. Source: caniuse.com

CSS-framework Tailwind CSS v2.0 supports dark-mode. (released on 18 Nov 2020)


EDIT (2 Dec 2020):

Google Chrome adds Dark Theme emulation to Dev Tools. Source: developer.chrome.com


EDIT (2 May 2022):

Currently 90% of the world can use dark mode CSS. Source: caniuse.com

Davy de Vries
  • 4,578
  • 2
  • 14
  • 29
  • 2
    Just tested it. If you change the theme in your mac os settings, then you need to restart the browser. Too bad it's not synced on the fly. – Herman Starikov Nov 18 '18 at 22:53
  • 3
    @HermanStarikov I posted a update on this issue you are describing. With the new Safari Technology Preview Release 71 you can toggle in realtime. – Davy de Vries Dec 07 '18 at 10:51
  • Nice! I made a little demo of what theming would look like with bootstrap: https://twitter.com/Hermanhasawish/status/1071517994302562305 – Herman Starikov Dec 08 '18 at 21:37
  • 2
    Is there a way to detect this in JavaScript? – Akash Kava May 08 '19 at 05:03
  • 9
    @AkashKava I Googled around, yes it’s possible if you use something like this: `window.matchMedia("(prefers-color-scheme: dark)").matches` If I have some spare time I will add a full javascript solution to my answer. – Davy de Vries May 08 '19 at 10:00
  • The way to see this in JS is in [this other answer](https://stackoverflow.com/a/57795518/9986421). – Stormblessed Feb 26 '20 at 00:19
  • Using prefers-color-scheme in also works. E.g.: `` and `` warning: in Firefox (88 for Ubuntu) `media="(prefers-color-scheme: dark)"` interfered badly with `title="Style Name"` which can be used to switch between alternate style sheets. Using the title attribute caused Firefox to not select the dark mode style sheet (the second). – Naradana Jun 02 '21 at 10:26
  • In Chromium 91 on Ubuntu 20 ` – Naradana Jun 02 '21 at 10:59
  • How does this work in Gmail or other email clients? We cannot get going. – Pentium10 Jul 07 '22 at 08:09
  • Your test page link currently yields some TLS certificate validation error (it requires HTTPS due to HSTS). – maxschlepzig Feb 04 '23 at 18:52
201

If you want to detect it from JS, you can use this code:

if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
    // dark mode
}

To watch for changes:

window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', e => {
    const newColorScheme = e.matches ? "dark" : "light";
});
Mark Szabo
  • 8,515
  • 3
  • 18
  • 26
  • 1
    Hi! This works great. I'm curious though — how exactly does this syntax work? – Stormblessed Feb 26 '20 at 00:22
  • 4
    @Stormblessed first it will check if the browser supports `matchMedia` and then it will try to match the `prefers-color-scheme: dark` string. If it matches we are in dark mode. – Mark Szabo Feb 28 '20 at 08:18
  • 3
    With the new Elvis operator this can be written as `if (window.matchMedia?('(prefers-color-scheme: dark)').matches) { }` – Mark Szabo Feb 28 '20 at 08:19
  • oh that makes sense! The syntax with .matches looked like it was doing the comparison between the first thing and the second or something. Thanks! – Stormblessed Feb 28 '20 at 15:12
  • Should be the checked answer. – podperson Mar 24 '20 at 18:25
  • 1
    @MarkSzabo Your code does work, but is not cross platform compatible like `addListener` see here: https://developer.mozilla.org/en-US/docs/Web/API/MediaQueryList/addListener So it should be: `window.matchMedia('(prefers-color-scheme: dark)').addListener(e => { this.darkMode = e.matches; });` – Stefan Rein Jul 17 '20 at 09:45
  • @StefanRein as far as I know all browser versions that support `matchMedia` also support `addEventListener`, so this should not cause errors. – Mark Szabo Jul 18 '20 at 11:31
  • @MarkSzabo my cordova app just crashed with `window.matchMedia('(prefers-color-scheme: dark)').addEventListener is not a function`. While on my desktop browser everything worked. It was a WKWebView iOS 13 with cordova-ios 5.1.1 – Stefan Rein Jul 19 '20 at 11:12
  • @StefanRein did you include feature checking like `window.matchMedia &&` ? – Mark Szabo Jul 19 '20 at 14:35
  • @MarkSzabo No, because the method `addListener` did work on the returned MediaQueryList of the matchMedia() method. Since matchMedia does exist it would still crash with a function call which not exists – Stefan Rein Jul 20 '20 at 04:56
  • Not working in mac 2021 – mercury Oct 23 '21 at 22:23
23

Spec has launched (see above), available as a media query. Something has already landed in Safari, see also here. So in theory you can do this in Safari/Webkit:

@media (prefers-dark-interface) { color: white; background: black }

On MDN a CSS media feature inverted-colors is mentioned. Plug: I blogged about dark mode here.

Jeff
  • 13,943
  • 11
  • 55
  • 103
Frank Lämmer
  • 2,165
  • 19
  • 26
  • 8
    **Do not use `inverted-colors` for detecting dark mode.** First of all, it won't work. Second of all, it's used for accessibility, NOT aesthetic. Some users use inverted mode to enhance the contrast of their screen, typical if they have impaired vision. Please do not change the appearance of your site given `inverted-colors` as it will, at best, not work how you want, and at worst it will frustrate those users. – Qix - MONICA WAS MISTREATED Oct 15 '20 at 03:08
15

According to Mozilla, here is the preferred method as of 2020

@media (prefers-color-scheme: dark) {
  body {
    background: #000;
  }
}
@media (prefers-color-scheme: light) {
  body {
    background: #fff;
  }
}

For Safari/Webkit you can use

@media (prefers-dark-interface) { background: #000; }
Aslam
  • 9,204
  • 4
  • 35
  • 51
5

I searched though Mozilla API, they don't seem to have any variables corresponding to the browser-windows color. Though i found a page that might help you: How to Use Operating System Styles in CSS. Despite the article-header the colors are different for Chrome and Firefox.

toeffe3
  • 83
  • 1
  • 7
0

Using BootStrap 5.3.0-alpha1 and based on Mark Szabo's answer, I used this (I was using TypeScript):

    window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => {
        switchColorScheme();
    });

    function switchColorScheme() {
        document.querySelector('html')!.dataset.bsTheme = window.matchMedia('(prefers-color-scheme: dark)').matches
            ? "dark"
            : "light";
    }

    switchColorScheme();

Before the page is loaded, it already detects the browser's current light or dark mode, and sets the bootstrap property on the element accordingly.

Chris
  • 4,212
  • 5
  • 37
  • 52
0

It's not official yet but you can use:

background-color: canvas color: canvasText

Current Official: https://www.w3.org/TR/css-color-3/ Draft Recommendation: https://www.w3.org/TR/css-color-4/

(Don't slam me for posting this. I'm not promoting it I'm just saying it works.)

  • 1
    Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Parking Master Jun 17 '23 at 12:21