Fast Track to Dark Mode with Styled Components

Posted on February 25, 2020

This post describes a fast track to dark mode with Styled Components and a couple of other packages which is currently implemented on this blog.

Note that we will not be discussing the implications or concept behind dark mode, there are enough articles on the web that do that already. Let’s get straight to business.

We will start with a ReactJS hook for dark mode. We will also add in the gatsby plugin that helps prevent flashing on load for the same hook.

npm i use-dark-mode gatsby-plugin-use-dark-mode

Now, we need a button to change the mode, we could add any button but let’s get the pre-made beautiful SVG button:

npm i react-dark-mode-toggle
button demo

Let’s split our theme to colors and others:

1const darkColors = {
2 background: `#121212`,
3 textColor: `rgba(255, 255, 255, 0.85)`,
4}
5const lightColors = {
6 background: `#FFFFFF`,
7 textColor: `rgba(0, 0, 0, 0.8)`,
8}
9const theme = {
10 other: {},
11}
12export default getTheme(mode) {
13 return {
14 ...theme,
15 colors: mode === 'light' ? lightColors : darkColors,
16 }
17}

Guide to using ThemeProvider in docs

Now, let’s wire the button and the hook together:

1import useDarkMode from 'use-dark-mode';
2import DarkModeToggle from 'react-dark-mode-toggle';
3
4import getTheme from './theme';
5
6function Layout({ children }) {
7 const darkMode = useDarkMode(false);
8 const theme = getTheme(darkMode.value ? 'dark' : 'light');
9 return (
10 <>
11 <header>
12 <DarkModeToggle
13 onChange={darkMode.toggle}
14 checked={darkMode.value}
15 size={50}
16 />
17 </header>
18 {children}
19 </>
20 );
21}
22
23export default App;

and that’s it! We have dark mode. You might have to adjust some other variables for hover styles and others, but this is a great start.

Bonus: Global Styles:

1import { createGlobalStyle } from 'styled-components';
2
3const GlobalStyles = createGlobalStyle`
4 body {
5 color: ${props => props.theme.colors.textColor};
6 background-color: ${props => props.theme.colors.background};
7 }
8 body.dark-mode {
9 img:not([src*=".svg"]) {
10 filter: grayscale(50%);
11 }
12 }
13`;
14
15export default GlobalStyles;
Buy me a coffeeBuy me a coffee