7

Lately I am updating my software to support dark mode, in response to research that looking at a paper-white background display is bad for the eyes and for sleep rhythms. Is there a way to detect from PHP that a user's browser and/or OS are set to Dark Mode? How about detecting that it is set to nighttime mode (reduction of blue colors)?

uiuii
  • 71
  • 1
  • 3
  • 3
    You can't, see here: https://stackoverflow.com/questions/50840168/how-to-detect-if-os-x-is-in-dark-mode-in-browsers#answer-51799496 – dustytrash Sep 18 '18 at 14:12
  • 1
    Possible duplicate of [How to detect if OS X is in dark mode in browsers?](https://stackoverflow.com/questions/50840168/how-to-detect-if-os-x-is-in-dark-mode-in-browsers) – naththedeveloper Sep 18 '18 at 14:36

2 Answers2

11

Unfortunately the dark mode detection methodology does not exist for server side-processing (including PHP).

  • All efforts thus-far by the W3C (and its sponsors) has been focused on client-side / Jamstack, and the Media Queries Level 5 specification uses a prefers-color-scheme media query for detection. This useful in both CSS and JavaScript.

  • There is a recommendation by Thomas Steiner (@DenverCoder9) from Google to implement a Proposed server-side client hint, but this has not been adopted (yet?) by the W3C or the browsers.

  • Either way - there is a significant drawback in server-side detection (both with Thomas' recommendation and my solution below) in that the server will only know about a state change (e.g. macOS "Auto" mode when night fall happens) on the next server request, or more visibly, the first load of the page.

  • The recommendation is to leave this detection on the client and projects like vinorodrigues/bootstrap-dark show how easy that can be - without server-side processing.

Having said that - there is a workaround:

The most efficient way is to leverage the js-cookie/js-cookie project, and include the following code into your HTML pages:

  <script src="https://cdn.jsdelivr.net/npm/js-cookie/dist/js.cookie.min.js"></script>
  <script>
    // code to set the `color_scheme` cookie
    var $color_scheme = Cookies.get("color_scheme");
    function get_color_scheme() {
      return (window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches) ? "dark" : "light";
    }
    function update_color_scheme() {
      Cookies.set("color_scheme", get_color_scheme());
    }
    // read & compare cookie `color-scheme`
    if ((typeof $color_scheme === "undefined") || (get_color_scheme() != $color_scheme))
      update_color_scheme();
    // detect changes and change the cookie
    if (window.matchMedia)
      window.matchMedia("(prefers-color-scheme: dark)").addListener( update_color_scheme );
  </script>

And then your PHP will detect this cookie like this:

  $color_scheme = isset($_COOKIE["color_scheme"]) ? $_COOKIE["color_scheme"] : false;
  if ($color_scheme === false) $color_scheme = 'light';  // fallback

Which you can use to load the CSS:

  // Load the CSS for the correct color-scheme
  if ($color_scheme == 'dark') {
    ?><link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/vinorodrigues/bootstrap-dark@0.0/dist/bootstrap-night.min.css"><?php
  } else {
    ?><link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0.css/bootstrap.css"><?php
  }

Or, like this:

  ?>You are in <?= $color_scheme ?> mode.<?php
3

Since PHP executes on the server without any knowledge of the client, there is no direct way of finding this out.

If it is possible to detect the color mode in JS, you could embed a small JS script to your site, that sets a cookie. Cookies are transmitted to the server on request, so PHP is able to query them.

Hendrik410
  • 33
  • 3