Wilson Staley

Adding Dark Mode to my Gatsby Site

December 22nd, 2020

I just added a dark mode to my site and it was super easy! To accomplish this, I used gatsby-plugin-dark-mode.

Here's how it works...

Step 1 - Installing the Plugin

Simply Install the plugin with npm install gatsby-plugin-dark-mode.

Then you can add it to your gatsby-config.js file like so:

plugins: [
  "gatsby-plugin-dark-mode",
  ...
]

This plugin provides you with a React component for implementing theme toggling in your site. It handles a lot of the hard parts of adding a dark mode for you. For example, it handles the browser code for persisting the theme. So if you set the site to dark mode, close the browser, and revisit the site later, it will remember which mode you had selected. It also automatically uses the prefers-color-scheme CSS media query, so if your system is configured to use dark color schemes when available, the site will first be opened in dark mode!

Step 2 - Adding the Toggle Component

I decided to toggle the dark mode by adding a nice little icon to the upper right hand corner of every page on my site. Since I am using a Header component on every page, it was easy to add this toggle inside the Header component:

import { ThemeToggler } from "gatsby-plugin-dark-mode"

<ThemeToggler>
  {({ theme, toggleTheme }) => (
    <div className={headerStyles.toggleTheme}>
      <FontAwesomeIcon
        icon={faMoon}
        onClick={() =>
          theme === "dark" ? toggleTheme("light") : toggleTheme("dark")
        }
      />
    </div>
  )}
</ThemeToggler>

As you can see, I am using a nifty little FontAwesome icon. If you would like to see how to use their icons in your React project, you can read more about it here.

The ThemeToggler component provides access to the theme's state ('dark' or 'light') as well as a function to toggle between those states. When you toggle between these states, a class of 'dark' or 'light' is applied to the body of your site.

Step 3 - Applying Relevant Styles

So now we have a class of 'dark' or 'light' on the body of our site, and we can toggle between states by clicking on the icon. But we still need a way to apply different styles depending on that class.

To do this, I used CSS variables scoped for the body:

body {
  --bg: #fff;
  --primaryText: #000;
  --secondaryText: #777;
  ...
  background-color: var(--bg);
}

body.dark {
  -webkit-font-smoothing: antialiased;
  --bg: #222831;
  --primaryText: #e8e8e8;
  --secondaryText: #9d9d9d;
  ...
}

So now every element inside the body will have access to the CSS variable, 'primaryText' for example, and the value of this variable will change depending on whether or not the body has a class of 'dark' applied to it. Now I can use these variables on any element on my site and they will change styles when the theme is toggled!

There's a lot you can do with this simple concept. I thought it would be fun to change the cursor's highlight color depending on the site's current theme😊

body *::selection {
  background: var(--link);
  color: #fff;
}

And that's all there is to it!

Created by Wilson Staley, © 2021