Start learning free

LESSON 118 OF 161 · FRONTEND: ACCESSIBLE, FAST, CORRECT

A Dark Mode Switch in JavaScript

Practice

The Corner Shop keeps its colors in CSS variables in styles.css. The :root rule sets --bg to #ffffff. The [data-theme="dark"] rule sets it to #121212, but only when the <html> element has data-theme="dark". Right now the "Dark mode" button changes its own state, but nothing changes <html>. So after a click, the check still prints --bg: #ffffff <- :root.

document.documentElement is the <html> element, and its dataset holds its data- attributes. A useEffect with [theme] runs after the first draw and again after every change to theme. That makes it the right place to update the page outside React. It is also where you save the choice in localStorage, which survives reloads. Here are the same tools used for a text-size setting:

document.documentElement.dataset.size = "large";  // <html data-size="large">
localStorage.setItem("size", "large");
localStorage.getItem("size");  // "large", or null on a first visit
window.matchMedia("(prefers-reduced-motion: reduce)").matches;  // true or false

On a first visit nothing is saved yet, so the page should follow the computer's setting. window.matchMedia("(prefers-color-scheme: dark)").matches is true when the system is set to dark. The check's browser is set to dark, so your page must print:

> open the page
    button: Dark mode (pressed)
    --bg: #121212   <- [data-theme="dark"]
> click "Dark mode"
    button: Dark mode
    --bg: #ffffff   <- :root
> the browser's localStorage
  theme = light
> reload the page
    button: Dark mode
    --bg: #ffffff   <- :root

Your task: in src/ThemeToggle.jsx, add an effect that puts theme on the <html> element as data-theme and saves it in localStorage under the key "theme". Then change startTheme so it returns the saved theme if there is one. If not, it returns "dark" when the system prefers dark, and "light" otherwise.


Assignment
Follow the Coding Tutorial to write the effect that applies and saves the theme, then make startTheme start from the saved choice or the system setting.


Hint
The effect's dependency list is [theme]. In startTheme, order matters: the visitor's saved choice comes before the system setting. getItem gives null when nothing is saved.


STEP 1 OF 6
    Ctrl + Enter to check

    Theme Toggle in JavaScript

    Keep going with JavaScript1,600+ step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free