Create a Dark Mode of your app using Styled Components
Many applications and software packages have begun shipping an optional dark mode that a user can enable as an alternative to the default lighter mode. Aside from the aesthetic differences, there are many other benefits mentioned ranging from being less taxing on your device’s battery consumption to actual improvements on your health.
While we’re not actually going to get into the alternative benefits from using the dark mode in this article, we will go through implementing it using React and Styled Components!
What we’re going to build
The application is going to consist of a few basic, styled elements including a button that will allow the user to toggle between a light and a dark mode. In addition to toggling the mode, it will also save the user’s preference so that their selection is remembered when they return.
A few tools we’re going to use to help us build the app:
- Create React App (Bootstrapping the app)
- Styled Components (Themeing)
- Local Storage (Save the user’s selection)
You can check out a demo of the finished project here.
Part 1: Bootstrapping the App
As mentioned above, we’re going to utilize Create React App as a way to get our application up and running. If you do not already have Create React App installed, you can install it with:
npm install -g create-react-app
To initialize our new application run:
create-react-app dark-mode-toggle
Change into our new project directory:
cd dark-mode-toggle
And finally, let’s install the only additional dependency we will need — styled components:
npm install styled-components --save
Part 2: Build the App with a Light Theme
We’re going to initially build the application without the dark mode, so start by deleting all of the files from the current src
directory of your project. Then let’s prepare the files:
- Inside of the
src
directory create two new folders —components
andthemes
- In the
src/components
directory, create anApp.js
,Button.js
,Card.js
, andContainer.js
file - In the
src/themes
directory, create alight.js
file - In the
src
directory, create anindex.js
andstyle.css
file
When the above is complete, your folder structure should resemble:
.
└── src
├── index.js
├── style.css
├── themes
| └── light.js
└── components
├── App.js
├── Button.js
├── Card.js
└── Container.js
Now, let’s start writing some actual code! We’ll start in the src/themes/light.js
file which will contain all of the colors required for the light mode.
In a real application, you will want to avoid naming conventions that pair 1:1 with a specific component and make them more universal, however, for the sake of this application, I’ve named the colors to their use-case.
Moving on to our src/index.js
file to initialize our React application:
In the src/index.js
file, we import the src/style.css
file. To be clear, this stylesheet will not contain any of our theme’s styles, but one rule to just remove the default margin on the body
element:
The next component we’re going to focus on will initially just provide the light theme we created above, but we will revisit it again later in this article when we add the logic to toggle the Dark theme. So, in src/components/App.js
we’re going to:
- Import the light theme that we created above
- Provide our theme using Styled Component’s
ThemeProvider
- Import and render the components that our app contains
In the src/components/App.js
file we just created, we reference our three remaining components — Container
, Card
, and Button
.
- The
Container
is responsible for centering our content in the viewport - The
Card
is responsible for visually separating our content from the rest of the page - The
Button
component will be used to toggle the dark mode later on in the article
When we build each of these components below, we are going to make reference to the theme that is provided in the src/components/App.js
file’s ThemeProvider
. You can read more about how themes work with styled components here.
For our purposes, any time we reference a color, we will pull it off of our theme object using ${props => props.theme.colors.ourColorProperty}:
At this point, you should have an app that resembles:
Part 3: Providing a Dark Theme
Since we have a basic app that consumes a theme, let’s add a new theme! Create a new file in the src/themes
directory called dark.js
.
Inside that file, we’re going to copy paste the object from src/themes/light.js
and just change the hex codes:
To test that our new theme works properly, let’s import it into our src/components/App.js
file and swap that into our theme provider:
Once the above changes have been made, you should see the dark version of the application:
The last piece of this puzzle is to provide the ability to actually toggle between these two modes. We will do this by:
- Utilizing the
useState
hook for ouruseDarkMode
state - Conditionally passing a theme into the
ThemeProvider
based on theuseDarkMode
state - Toggling the
useDarkMode
state when the button is clicked - Saving the
useDarkMode
state into local storage to remember the user’s preference upon returning
Once that is all hooked up, clicked the button should toggle the theme mode and save it into local storage. You can test this out by enabling dark mode and refreshing, and you should still see the dark mode!
Final Thoughts
- A
button
is not the greatest of UX patterns to toggle a theme, so in a production application, you may want to consider something more appropriate like a checkbox! - While this article focused on a dark mode, there’s no limit to the number of themes you could offer, so you could swap the boolean value for a selection of some sort that provides more options to the end user
- As mentioned a bit earlier, the naming conventions used in the theme is far from ideal for a larger application, so more thought should typically be put into the names
- The colors used in this application are from the Nord Color Theme