How I Added Dark Mode In 20 Lines

Thu, 23 Apr 2020

Step 1.

Install dependencies.

npm install --save use-dark-mode gatsby-plugin-use-dark-mode gatsby-plugin-sass

Step 2.

Add the plugin to your gatsby config.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
module.exports = {  
  ...,  
  plugins: [  
    `gatsby-plugin-sass`,  
    {  
      resolve: "gatsby-plugin-use-dark-mode",  
      options: {  
        classNameDark: "dark-mode",  
        classNameLight: "light-mode",  
        storageKey: "darkMode",  
        minify: true,  
      },  
    },  
   ...,  
  ],  
}

gatsby-plugin-use-dark-mode adds a classname to the body of the html showing what state we are in, dark or light mode. This is calculated using the storageKey(a cookie) that sits on the client. This defaults to the users default setting on their device.

Step 3.

Create our colours in a colors.scss file.

1
2
3
4
5
6
7
8
9
10
11
12
13
$brand-colors: ('white', #ffffff, #1c1c1c), ('black', #1c1c1c, white),  
  ('light-brown', #e1d2af, #e1d2af), ('grey', #2e4052, #f9f9f9),  
  ('light-grey', #f9f9f9, #121212), ('blue', #35466d, #49aab7);  
@each $color in $brand-colors {  
  .is-#{nth($color,1)} {  
    color: nth($color, 2);  
  }  
body.dark-mode {  
    .is-#{nth($color,1)} {  
      color: nth($color, 3);  
    }  
  }  
}

Wait? Whats going on here?!

First I am defining some brand colours in the following format:

(‘name-of-colour’, #colour-in-light-mode’, #colour-in-dark-mode)

Then I iterate through each colour and create a classnames with the name and hex for light mode so for example:

('white', #ffffff, #1c1c1c)

creates in the loop:

1
2
3
.is-white {  
    color: #ffffff;  
  }

I also add a second instance of this class that overrides when dark mode has been added as a class name to the body. This uses the second colour so in our example with white we create:

1
2
3
4
5
body.dark-mode {  
    .is-white {  
      color: #1c1c1c;  
    }  
}

You can repeat this process for background and border colours too!

Step 4.

Import colors.scss in global.scss.

1
@import './colors';

Step 5.

Add scss to gatsby-browser.js.

1
require("./src/styles/global.scss")

Step 6.

Create a new react component that acts as a mode switch.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import React from "react";  
import useDarkMode from "use-dark-mode";  
export default (props) => {  
  const darkMode = useDarkMode(false); //defaults to false  
  return (  
    <div>  
      {darkMode.value ? (  
        <button  
          type="button"  
          aria-label="light mode"  
          onClick={darkMode.disable}  
        >  
          <h2>To Light Mode</h2>  
        </button>  
      ) : (  
        <button type="button" aria-label="dark mode" onClick={darkMode.enable}>  
          <h2>To Dark Mode</h2>  
        </button>  
      )}  
    </div>  
  );  
};

Step 7.

Use our new classnames in any react component.

1
2
3
4
5
6
7
8
import React from "react";  
export default () => {  
  return (  
    <div>  
      <h4 className="is-white">Text colour dependant on mode!</h4>  
    </div>  
  );  
};

You’re all done! 🎉

1

...

...

...

...

Want to know when I post something new? Subscribe to my newsletter. 🚀

I’m Sam Larsen-Disney. I document the cool things I learn and enjoy helping the next generation to code. My site has no ads or sponsors. If you enjoy my content, please consider supporting what I do.