Who doesn't want a dark theme on their website! Not only does it help us focus better, but also keeps our eyes safer π€.
The blog might add value if you belong to either of these situations -
Maybe you have been in a place wherein you want to implement a dark theme for your website but are struggling around the same π΅.
You are starting out with React, so this might just be another fun exercise for you to try π.
Prerequisites
- Basic knowledge of React and terminologies (state, props, etc.)
- Basic knowledge of CSS
- Will to learn π
Spin up a new React Project β¨
You could use your local development environment or maybe use a sandbox.
Noteπ - If using local setup prefer cleaning up the factory code before moving further.
Also, I will be using class based components for this one - not using React Hooks.
Create a simple page
In our App()
, just return a div
for the time being. (Can use a button
as well)
Add state to our app
We cannot do much with a dumb component when it comes to embedding logic inside of it. So we need to add state
to the React component.
Add a state called isDarkThemeEnabled
to the App
component and set it to false
.
Creating the theme switcher logic π‘
This is the crux of the entire problem.
How to build the theme switcher / toggler ?
This might become simple, if you try to draw an analogy to a light bulb. A light bulb has two states on
and off
.
At any given point of time it is in one of the either states.
Now, imagine the theme switcher to be a bulb and try to map the idea.
You got it! π If the theme switcher is imagined to be a light bulb, light mode
becomes on
and dark mode
becomes off
or vice-versa.
Now, how to toggle the state ? Pretty simple, just flip the current state whenever a certain event fires.
In simpler terms - on clicking a button change the state value from true
to false
or vice versa.
Implementing the theme switcher logic
Now, as we have designed the approach it's good time to start coding up the idea.
FYI for changing state in React we use the setState
function. You can read about the setState
API from here.
Let's create a clickHandler
and embed the state-toggler logic inside of it.
Pass this clickHandler
to the onClick
prop of the div, to trigger the function whenever user clicks on the div.
Adding SVG to our app
I want to let the user know which mode he can currently switch to. Can be accomplished with text, but what better than using SVG icons to enhance the UI !π
I will be using heroicons for high quality SVG icons.
Create two files in your /src
directory, for two SVG icons for the two states. I will be using a Moon and a Sun SVG in this case.
To use any SVG in our React app, we can directly use them in our code or import the SVG as a React Component. I prefer the latter as it helps to keep the code cleaner.
This is how we import an SVG icon as a React component -
import {ReactComponent as Moon} from './moon.svg';
We need to toggle the SVG icons as well to suit our purpose. For this we will use conditional rendering
.
This is a gem π. You can read about this here.
The idea is, whenever isDarkThemeEnabled
is true
we need the sun
SVG to show up else the moon
SVG should show up.
This is how the app looks right now. You're almost there.π
Let's style up our app
When dark mode
is enabled we would want to paint our app background dark. So, for this we would prefer applying classNames conditionally
.
You can read on this from here.
We would be using JSX expression
and Template Literals
for this. When isDarkThemeEnabled
is set to true
, which means dark mode
is enabled, we would append a className
to the App
className.
className={`App ${isDarkThemeEnabled && "dark-mode"}`}
Now lets add some style for the .App.dark-mode
class.
Let's also style up the SVG icons π
. Add a className of moon
and sun
to <Moon />
and <Sun />
components respectively.
This is how the App code looks right now.
import "./styles.css";
import React from "react";
import { ReactComponent as Moon } from "./moon.svg";
import { ReactComponent as Sun } from "./sun.svg";
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
isDarkThemeEnabled: false,
};
}
handleClick = () => {
const { isDarkThemeEnabled } = this.state;
this.setState({
isDarkThemeEnabled: !isDarkThemeEnabled,
});
};
render() {
const { isDarkThemeEnabled } = this.state;
return (
<div className={`App ${isDarkThemeEnabled && "dark-mode"}`}>
<div className="toggler-btn" onClick={this.handleClick}>
{isDarkThemeEnabled ? (
<Sun className="sun" />
) : (
<Moon className="moon" />
)}
</div>
</div>
);
}
}
export default App;
Add desired styles in the styles.css
.
β¨ Add a transition time to the wrapper class to make the color switch smoother. I added transition: 0.3s ease
to .App
.
This is how the App looks finally!
Note - I have added some additional styles and animations.
For a larger websites use css variables
to make painting UI components on theme toggle easier.
Feel free to play around with the sandbox.
Conclusion
Congratulations!! ππ You made it till the end. If you're still here chances are you probably liked the blog.
You can also make improvisations to this simple project and share them. This would help in getting the fundamentals stronger π π.
Do let me know how you liked the blog and where I need to improve. Would be eagerly waiting for feedback!
Top comments (6)
Great!
I also wrote an article about how to implement it in the old project Using the PostCSS plugin Let your WebApp support dark mode
Thanks a lot! π Your article looks awesome!
Shouldn't you use setState with a snapshot of previous state? It should not be directly mutated.
True that! Thanks for this.
Why not to use params and just change it and it will effect all your code
Didn't think of this idea! Will surely try this out.