How I Implemented the Dark Mode on My Website

Published on 2019.12.26

francoscarpa.com can be displayed in clear and dark mode. Clear mode is suitable when you are in a bright environment, and dark mode is best when the light around you is low, since it is less tiring on the eyes. You can switch between the two modes using the button at the top. When you change the mode, it is stored as a preference and maintained for each subsequent visit, until you change it. I’ll explain how I implemented this feature.

The Button

I wrote the button’s code from scratch. It is an SVG, which consists of a rectangle with rounded edges and a circle. I was inspired by the iOS Switches. I like them as they are simple to emulate. When the button is disabled, its background is gray and the circle is on the left. When it’s enabled, the rectangle’s background turns green and the circle moves to the right. Visual feedback is also provided through animations, which improves UX due to the sense of transition perceived as the button status changes.

The HTML code that generates the button is this:

<svg id="themeButton" width="60" height="30">
  <rect x="0" y="0" width="60" height="30" fill="#ddd" fill="15" />
  <circle onclick="toggleTheme()" cx="15" cy="15" r="12" fill="#fff" /> 
</svg>

An onclick() event is connected to the circle. The button is activated only by pressing the circle, not the surrounding rectangle. This is why it may seem that the button does not work when you press it. Therefore, you must click on the circle.

The JavaScript Code

Operation of the mode change is based on this code:

function toggleTheme() {
  if (localStorage.getItem("theme") !== "dark") {               // if the theme is dark
    themeButton.children[0].setAttribute("fill", "#6ee559");    // color the button green
    themeButton.children[1].setAttribute("cx", "45");           // move the circle inside the button to the right
    root.id = "dark";                                           // set the id of the html element to "dark"
    localStorage.setItem("theme", root.id);                     // save the info about the dark theme 
    localStorage.setItem("themeButtonFill", "#6ee559");         // ...
    localStorage.setItem("themeButtonX", "45");                 // ...
  } else {                                                      // if the theme id clear
      themeButton.children[0].setAttribute("fill", "#ddd");     // color the button gray
      themeButton.children[1].setAttribute("cx", "15");         // move the circle inside the button to the left
      root.id = "";                                             // set the id of the html element to ""  
      localStorage.setItem("theme", root.id);                   // save the info about the clear theme 
      localStorage.setItem("themeButtonFill", "#ddd");          // ...
      localStorage.setItem("themeButtonX", "15");               // ...
    }
  };
        
var root = document.documentElement;                            // references the html element
var themeButton = document.getElementById("themeButton");       // references the button to change the mode
        
if (localStorage.getItem("theme")) {                                                        // if the "theme" property is set on localStorage
  themeButton.children[0].setAttribute("fill", localStorage.getItem("themeButtonFill"));    // set the "fill" attribute using the key of the same name on localStorage 
  themeButton.children[1].setAttribute("cx", localStorage.getItem("themeButtonX"));         // set the "cx" attribute using the key of the same name on localStorage
  root.id = "dark";
}

The toggleTheme() function manages the transition from one mode to another, alternating between the two. A couple of variables store the html element and the button. The final if-statement is necessary to save the currently selected theme upon exiting the current page. It would be annoying to visit a different page and later return to the default clear theme. The option to save settings is possible thanks to the Web Storage API, in particular the localStorage mechanism, which provides persistent storage space for each site. The preferences are maintained even when you leave the site and return to it later. Therefore, through this API, not only is the current theme maintained by navigating through the various pages, but also the last selected theme is shown when you visit the site at a later time.

The toggleTheme() function updates the theme to be displayed by calling the setItem() method, which allows you to store couples of values. Since the light theme is set by default, to check if the dark theme should be provided instead, the final if-statement is responsible for calling the getItem() method to read the value. The function code is executed each time a page is loaded; this way the appropriate theme is shown every time you visit francoscarpa.com.

If you have any questions, ideas, advice, suggestion, or if you want to tell me something or get in touch with me, please: do it! You can find me on Twitter (you can click on the profile picture on the homepage to send me a Direct Message), or you can e-mail me.