A Simple Way to Implement Dark Mode in React

Tyler J Funk
Nov 15, 2020 · 5 min read
Photo by Glen Alejandro on Unsplash

This week I’ve decided to write about how to implement dark mode into a React app. In order to demonstrate this, I will be editing a super simple app I created for a previous post I wrote about how to make only specific elements printable while hiding others. I appropriately named the app “PrintaBull”.

What I’ll be doing:

  1. Creating the state that will hold the info about whether the user currently has “Light” or “Dark” mode selected.
  2. Adding a way to toggle which mode is currently active.
  3. Updating JSX elements to be ready for “Dark Mode” styling changes with ternary statements on each element’s id.
  4. Applying “Dark Mode” styling changes to each element.

First, let’s take a look at the app, and the code I am starting with. Please keep in mind this app is just made for demos, and is clearly not the pinnacle of my web development career thus far.

We’ll call this our “Light” mode

The above result was achieved with the code below:

Create isDarkModeActive State

Like the title of this section suggests, I’ll be naming the state isDarkModeActive. I like to use React Hooks, so I’ll be creating the state with the useState hook, and then creating my variable/function to update that variable like so:

const [isDarkModeActive, setIsDarkModeActive] = useState(false)

Now I can access the variable isDarkModeActive which will allow me to toggle the style of each element by using a ternary statement based on whether this variable is true or false.

Make a Way to Toggle isDarkModeActive

In order to make it possible for a user to toggle this mode themselves, we have to give them a way to do so, it could be a button, but I will choose to be a little more creative, and make a toggle switch looking thing from scratch.

I’ll make the switch by having a container, which will hold 2 elements, one that will say “Light” and another which will say “Dark”. When the user clicks one or the other, isDarkModeActive should flip to the opposite boolean, indicating to the other elements which styling they should be using.

First, I’ll create a simple helper function that will flip the boolean held in the isDarkModeActive state. This will be called upon clicking either element inside the toggle switch:

const switchModes = (mode) => {
if(mode === "light") {
setIsDarkModeActive(false)
} else if(mode === "dark") {
setIsDarkModeActive(true)
}
}

Here is the JSX which creates our toggle box, and calls our helper function onClick:

<div className={isDarkModeActive ? "toggle-dark": "toggle-light"}
<h4 className="light-mode" onClick={() => switchModes("light")}>
Light
</h4>
<h4 className="dark-mode" onClick={() => switchModes("dark")}>
Dark
</h4>
</div>

Finally, the styling/CSS that I used for the toggle box:

.toggle-dark, .toggle-light {
display: flex;
padding: 3px;
border-radius: 4px;
position: absolute;
top: 5px;
right: 5px;
}
.toggle-dark {
background-color: rgb(50, 50, 50); // almost white
}
.toggle-light {
background-color: rgb(250, 250, 250); // dark gray
}
.dark-mode, .light-mode {
margin: 3px;
padding: 3px;
cursor: pointer;
border-radius: 4px;
width: 50px;
text-align: center;
}
.dark-mode {
background-color: rgb(50, 50, 50);
color: rgb(250, 250, 250);
}
.light-mode {
background-color: rgb(250, 250, 250);
color: rgb(50, 50, 50);
}

Creates this effect:

Update the Other JSX Elements

Now that we have our toggle element set up, and it changes our isDarkModeActive state when clicked, we can adjust the original elements to conditionally change their className based on the current state.

This can be tedious for apps that already have a ton of elements, and I’m sure there is more than one way to do this. This is just the way I know how to make it work.

For each element, we are going to add a ternary statement for className which tells the element what styling to use.

As a quick example, I’ll show how I changed the <header> tag, this is how it looked originally:

<header className="app-header">
...
</header>

And after:

<header className={
isDarkModeActive ?
"app-header dark-header" :
"app-header"
}>
...
</header>

If we go through each element that needs to be inverted and change them in a similar way, we can conditionally customize the style, and make them fit the dark mode theme.

Final Styling Touches

For this app, I see about 6 elements I want to change when dark mode is selected; things that need to be inverted:

  1. Logo
  2. App title
  3. Print button
  4. Header background (darker)
  5. White background
  6. Black text

Once all the elements have the ternary statements like the one discussed above, we can go through and make each dark mode element actually change when the user clicks the “Dark” or “Light” button in our toggle switch.

I will briefly go over each styling change I made, although most of it is self explanatory:

Logo — For this, all I had to do was create an inverted logo, then make the src attribute change based on the state of isDarkModeActive:

<img className="printabull-logo"
src={isDarkModeActive ? InvertedPrintaBullLogo : PrintaBullLogo}
alt="PrintaBull logo">
</img>

App title — Added “dark” className of dark-title and changed the color of the text to match my toggle switch (almost white):

.dark-title {
color: rgb(250, 250, 250);
}

Print button — Added “dark” className of dark-button, changed the color of the button to be a darker blue, and also changed the text to an almost white:

.dark-button {
background-color: rgb(0, 37, 68);
color: rgb(250, 250, 250);
}

Header background — Added “dark” className of dark-header, changed the background color to be a dark blue instead of a bright blue:

.dark-header {
background-color: rgb(0, 68, 124);
}

White background & Black text— Added “dark” className of dark-app, changed the background of the entire app to match the dark gray of the toggle switch, and the color of the text to match the white from the toggle switch:

.dark-header {
background-color: rgb(50, 50, 50);
color: rgb(250, 250, 250);
}

Result & Conclusion

Let’s take a look at the results and put all the code together for one last look:

SD is default for me, make sure to select HD in the GIF settings if it is for you too!

There you have it, a fully custom made dark mode feature for your React app!

Below I will show all the code again for those interested in seeing all changes:

Thanks for reading, sorry if this was a bit elementary at times, but hopefully it taught someone out there something about conditional styling and how it can be used to create a custom dark mode feature in React.

As always, happy hacking!

The Startup

Get smarter at building your thing. Join The Startup’s +724K followers.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store