How to Add Dark Mode to Your React App

How to Add Dark Mode to Your React App

Adding dark mode to your React app ... Note: I use Emotion as a preference, but you can obviously use CSS modules or even inline

While working on a React app, I wanted to implement a day/night mode feature that allows the user to select whether or not they want to use a light or dark theme. Dark mode is becoming increasingly popular in app and software design. Aside from looking pretty cool, dark mode can help with device-energy conservation and reducing eye strain. For more on the science behind dark mode, check out this article in The Observer.

In this post, I’ll demonstrate how easy it was for me to implement this new design trend in my React app. There’s a lot more CSS involved in my application, but in order to remain concise, I’ll only provide the CSS relevant to my day-/night-mode functionality. First, let me provide some context.

My React app is an online text editor. My App component has a white background and black for the font color. This is the consistent color scheme throughout my application. I really am pushing the boundaries of contemporary web design.

Below is my App component.

import React, {Component} from 'react';
import './App.css';
import SizeContainer from './components/SizeContainer.js';
import {withRouter} from 'react-router-dom';
import { connect } from 'react-redux'; 
const App = (props) => {     
   return (      
      <div className={!props.mode ? "App" : 'night'}>        
         <h1 style={{height: 50, marginBottom: 0, padding: 5}}>
           React Editor
         <SizeContainer mode={props.mode}/>      
const mapStateToProps = (state) => {  
   return {      
      mode: state.mode  
export default withRouter(connect(mapStateToProps) (App));

As you can see, my App component has access to the mode prop via mapStateToProps. This prop is stored in my reducer and is accessible by any components I choose to export with connect. While Redux isn’t necessary for this functionality, I find it does make the process of applying the styles easier while keeping my components lean and mean. For more on Redux, check out the documentation.

Below is my reducer:

export default function rootReducer(state={mode: false}, action){
      case "CHANGE_MODE":      
         var mode = !state.mode        
         return {...state, mode}      
         return state    

When CHANGE_MODE is called, all that needs to be done is to get the current value of mode in my reducer’s state (true/false) and assign it the opposite value of what it currently is.

If state.mode is true, then !state.mode will equal false — and vice versa. No payload is necessary for this action. Now that we see how this is handled in the reducer, let’s take a look at the CHANGE_MODE action in our actions file.

export function changeMode(){  
   return {    
      type: "CHANGE_MODE"  

Since there’s no payload and the toggle operation is happening in the reducer, all we need to do is call this function in one of our components whenever we want to toggle the theme of the app. This brings me to my next component: SizeContainer.

Since I’m passing props.mode from the App to the SizeContainer, the child elements in the SizeContainer will also have access to the props.mode. This is important for one child component in particular: Buttons.

import React from 'react';
import {FaFileCode, FaLightbulb} from "react-icons/fa";
import {withRouter} from 'react-router-dom';
import { connect } from 'react-redux';
import { changeMode } from './../actions'
const Buttons  = (props) => {
    var {mode, changeMode} = props;
      <div className='buttonsContainer' >
           <div className='buttons' onClick={changeMode}>
              <span className="tooltiptext">
                 {mode ? "Day Mode" : "Night Mode"}
            <div className='buttons'>
               <span className="tooltiptext">
                   Download Code
export default withRouter(connect(null, {changeMode}) (Buttons))

The above code will render the below two button — one has a light-bulb icon, the other a code-file icon.

This is image title

As you can probably guess, the button with the light bulb icon will control the dark-mode toggle. No need to worry about the second button for now. Pay attention to the below line.

import { changeMode } from './../actions'

This is the changeMode function that gets exported from our actions. This function is added the light bulb button as an onClick event. Click the button, and execute the action to change the mode. Simple, no?

The tool tip for the light-bulb button will say either “Day Mode” if props.mode is true (meaning, dark mode is active), or if it’s false (dark mode is off), it’ll read “Night Mode”.

This is image title

In this instance, dark mode has not been initiated — hence the white background and “Night Mode” tooltip

Now that we have our React app set up, let’s get to the CSS.

.App {  
   text-align: center;  
   height: 100%; 
   transition: background-color 0.3s, color 0.3s;

When dark mode isn’t selected, our CSS is pretty straightforward. Since white is the default background color and black is the default font color of HTML, we don’t need to specify them here.

All we need to specify is the height and width of the App (we want it to take up the whole page) and the transition.

By specifying a background-color and color transition (both 0.3s), this will ensure our transition from day to night mode is smooth. Otherwise, it’ll look more like a jarring flash than a smooth transition from day to night.

Now that we have our default styles, let’s get down to business with dark mode CSS.

.night {
  text-align: center;
  height: 100%;
  width: 100%;  
  background-color: black;
  transition: background-color 0.3s, color 0.3s;

We declare the styles for the .night class name and explicitly state the background color and color as to prevent the HTML from using the default values. This one also has a transition: background-color 0.3s, color 0.3s; This will ensure that when we transition from dark backto light mode, the transition will remain smooth.

If you remember from earlier in the article, our App component’s className is determined by the value of props.mode. If props.mode is false, then use className="App"; otherwise, use className="night".

The above CSS satisfies the theme change for our App component, but to ensure that it applies the necessary styles to all child elements, we need to add a few more lines.

.night h1, .night h2, .night div, .night textarea{
  background-color: black;
  color: white;
  transition: background-color 0.3s, color 0.3s;

This will apply the background color and text color changes to any h1, h2, p, div, and textarea elements that fall within our App component.

These elements comprise the app’s text editor sections (textarea) and their titles (h2). The h1 is the title of the app itself, and pretty much everything is housed either in its own or in a parent’s div container.

By putting .night in front of all of these elements, we can target these specific child tags when we change the theme.

It’s also worth noting that here we use a descendant selector, identified by the space between .night and an HTML tag. This will select all child instances of an element that falls under .night. We don’t use >, the child selector, as it would only select immediate children of an element. We also don’t use + , the adjacent sibling selector, which would only select siblings. For more on CSS combinators, check out this really awesome article.

We’re almost done, but there are a few more things we need to consider. First, there are a few elements don’t want to change the color or background-color of (at least for now), such as the navy blue buttons. Whether or not the mode is dark or light, I want them to remain navy blue and have white icons. To ensure the className switch doesn’t affect these buttons, I can add the following CSS.

.night .buttons{  background-color: navy;}

By putting this line in my App.css file, I can prevent the previously mentioned CSS from changing the buttons’ styles. Previously, I thought that this line had to come afterthe original .night CSS since CSS is cascading by design and uses precedence to determine the style applied to an element.

In reality, where I put this line does not matter. Since we are using a class selector to target the buttons, the .night div styles will not be applied as the level of specificity is lower than .night .buttons. For more information, please read the MDN docs on specificity.

The above logic can also be applied for my last element, which I would like to keep independent from dark mode: my output container. This section, which has the class name of .view, is where the user’s code (composed of by combining the top three sections) will be running, and since that output area should only reflect the code written by the user, we should ensure that the default styles are enforced unless the user types new ones in the CSS section.

.night .view {  background-color: white;}

The rest of the output will be inserted into an iframe, which is a child of .view. This means the styles from the user will be completely separate from that of my app’s. Preserving the background color of the output container is all that’s needed.

Below is our final result.

This is image title

There you have it. With just a few extra lines of CSS and a little bit of props logic, your React app can have dark mode implemented efficiently and effectively.

reactjs javascript programming

Bootstrap 5 Complete Course with Examples

Bootstrap 5 Tutorial - Bootstrap 5 Crash Course for Beginners

Nest.JS Tutorial for Beginners

Hello Vue 3: A First Look at Vue 3 and the Composition API

Building a simple Applications with Vue 3

Deno Crash Course: Explore Deno and Create a full REST API with Deno

How to Build a Real-time Chat App with Deno and WebSockets

Convert HTML to Markdown Online

HTML entity encoder decoder Online

Learning JavaScript: Development Environments for JavaScript Programming

One of the nice things about learning JavaScript these days is that there is a plethora of choices for writing and running JavaScript code. In this article, I’m going to describe a few of these environments and show you the environment I’ll be using in this series of articles.

Learning JavaScript: Data Types and Variables

To paraphrase the title of an old computer science textbook, “Algorithms + Data = Programs.” The first step in learning a programming language such as JavaScript is to learn what types of data the language can work with. The second step is to learn how to store that data in variables. In this article I’ll discuss the different types of data you can work with in a JavaScript program and how to create and use variables to store and manipulate that data.

[ Professor JavaScript ]: Introduction

Professor JavaScript is a JavaScript online learning courses YouTube Channel. Students can learn how to develop codes with JavaScript from basic to advanced levels through the online courses in this YouTube channel.

From imperative to declarative JavaScript

In this post, I will explain why declarative code is better than imperative code. Then I will list some techniques to convert imperative JavaScript to a declarative one in common situations.

JavaScript Memory Management System

The main goal of this article is help to readers to understand that how memory management system performs in JavaScript. I will use a shorthand such as GC which means Garbage Collection. When the browsers use Javascript, they need any memory location to store objects, functions, and all other things. Let’s deep in dive that how things going to work in GC.