{"id":312285,"date":"2020-07-01T07:47:02","date_gmt":"2020-07-01T14:47:02","guid":{"rendered":"https:\/\/css-tricks.com\/?p=312285"},"modified":"2021-10-24T08:28:16","modified_gmt":"2021-10-24T15:28:16","slug":"a-complete-guide-to-dark-mode-on-the-web","status":"publish","type":"post","link":"https:\/\/css-tricks.com\/a-complete-guide-to-dark-mode-on-the-web\/","title":{"rendered":"A Complete Guide to Dark Mode on the Web"},"content":{"rendered":"\n

Dark mode has gained a lot of traction recently. Like Apple, for instance, has added dark mode to its iOS and MacOS operating systems. Windows and Google have done the same. <\/p>\n\n\n\n

\"\"
DuckDuckGo’s light and dark themes<\/figcaption><\/figure>\n\n\n\n

Let\u2019s get into dark mode in the context of websites<\/strong>. We\u2019ll delve into different options and approaches to implementing a dark mode design and the technical considerations they entail. We\u2019ll also touch upon some design tips along the way.<\/p>\n\n\n\n

Table of Contents<\/h4>\n\n\n
  1. Toggling Themes<\/a><\/li>
  2. Dark Mode at the Operating System Level<\/a><\/li>
  3. Storing a User’s Preferences<\/a><\/li>
  4. Handling User Agent Styles<\/a><\/li>
  5. Combining Approaches<\/a><\/li>
  6. Design Considerations<\/a><\/li>
  7. Dark Mode in the Wild<\/a><\/li>
  8. Dark Mode or No Dark Mode?<\/a><\/li><\/ol>\n<\/div><\/div>\n\n\n\n
    \n\n\n\n
    \n\n\n

    Toggling Themes<\/h3>\n\n\n

    The typical scenario is that you already have a light theme for your site, and you\u2019re interested in making a darker counterpart. Or, even if you\u2019re starting from scratch, you\u2019ll have both themes: light and dark. One theme should be defined as the default that users get on first visit, which is the light theme in most cases (though we can let the user\u2019s browser make that choice for us, as we\u2019ll see). There also should be a way to switch to the other theme (which can be done automatically, as we\u2019ll also see) \u2014 as in, the user clicks a button and the color theme changes.<\/p>\n\n\n\n

    There several approaches to go about doing this:<\/p>\n\n\n\n

    \n
    \n

    Using a Body Class<\/h4><\/summary>\n\n\n\n

    The trick here is to swap out a class that can be a hook for changing a style anywhere on the page.<\/p>\n\n\n\n

    <body class=\"dark-theme || light-theme\"><\/code><\/pre>\n\n\n\n

    Here’s a script for a button that will toggle that class, for example:<\/p>\n\n\n\n

    \/\/ Select the button\nconst btn = document.querySelector('.btn-toggle');\n\n\/\/ Listen for a click on the button\nbtn.addEventListener('click', function() {\n  \/\/ Then toggle (add\/remove) the .dark-theme class to the body\n  document.body.classList.toggle('dark-theme');  \n})<\/code><\/pre>\n\n\n\n

    Here’s how we can use that idea:<\/p>\n\n\n\n

    <body>\n\u00a0 <button class=\"btn-toggle\">Toggle Dark Mode<\/button>\n\u00a0 <h1>Hey there! This is just a title<\/h1>\n\u00a0 <p>I am just a boring text, existing here solely for the purpose of this demo<\/p>\n\u00a0 <p>And I am just another one like the one above me, because two is better than having only one<\/p>\n\u00a0 <a href=\"#\">I am a link, don't click me!<\/a>\n<\/body><\/code><\/pre>\n\n\n\n

    The general idea of this approach is to style things up as we normally would, call that our \u201cdefault\u201d mode, then create a complete set of color styles using a class set on the <body><\/code>  element we can use as a \u201cdark\u201d mode.<\/p>\n\n\n\n

    Let\u2019s say our default is a light color scheme. All of those \u201clight\u201d styles are written exactly the same way you normally write CSS. Given our HTML, let\u2019s apply some global styling to the body and to links.<\/p>\n\n\n\n

    body {\n\u00a0 color: #222;\n\u00a0 background: #fff;\n}\na {\n\u00a0 color: #0033cc;\n}<\/code><\/pre>\n\n\n\n

    Good good. We have dark text (#222<\/code>) and dark links (#0033cc<\/code>) on a light background (#fff<\/code>). Our \u201cdefault\u201d theme is off to a solid start.<\/p>\n\n\n\n

    Now let\u2019s redefine those property values, this time set on a different body class:<\/p>\n\n\n\n

    body {\n\u00a0 color: #222;\n\u00a0 background: #fff;\n}\na {\n\u00a0 color: #0033cc;\n}\n\u2028\n\/* Dark Mode styles *\/\nbody.dark-theme {\n\u00a0 color: #eee;\n\u00a0 background: #121212;\n}\nbody.dark-theme a {\n\u00a0 color: #809fff;\n}<\/code><\/pre>\n\n\n\n

    Dark theme styles will be descendants of the same parent class \u2014 which is .dark-theme<\/code> in this example \u2014 which we\u2019ve applied to the <body><\/code> tag.<\/p>\n\n\n\n

    How do we \u201cswitch\u201d body classes to access the dark styles? We can use JavaScript! We\u2019ll select the button class (.btn-toggle<\/code>), add a listener for when it\u2019s clicked, then add the dark theme class (.dark-theme<\/code>) to the body element\u2019s class list. That effectively overrides all of the \u201clight\u201d colors we set, thanks to the cascade and specificity. <\/p>\n\n\n\n

    Here\u2019s the complete code working in action. Click the toggle button to toggle in and out of dark mode.<\/p>\n\n\n\n