Theme Switcher
Build a toggle that switches the color scheme of the page between light and dark modes.
Solution
Headline
Section
This solution toggles CSS root values for font and background colours.
If light we use:
--fontColor: black; --bgColor: white;
If dark we use:
--fontColor: white; --bgColor: black;
Better solutions would also take account of the users preferences. You can see from this article how you need to access the system settings with media queries.
Explanation
isDark useState
The user preference for light
or dark
mode is stored in the state variable, isDark
.
toggleDarkMode function
The toggleDarkMode
function very simply returns the opposite of the current state. This is attached to the Toggle Theme
button.
Adding the style to elements
A conditional style has been added to the container element with a ternary operator
with either lightMode
and darkMode
being assigned.
The trick to changing the styles in CSS
The use of CSS Variables
controls the output colours.
Both lightMode
and darkMode
have their own values for the variables --fontColor
and --bgColor
.
Look to the other CSS classes to see how those variables have been used to assign key colours. This means they can alter based off of which of the two classes lightMode
or darkMode
is used.
Code
import { useState } from "react";
import styles from "./Solution.module.css";
const Solution = () => {
const [isDark, setIsDark] = useState(false);
const toggleDarkMode = () => setIsDark((prevMode) => !prevMode);
return (
<div
className={`${styles.container} ${
isDark ? styles.darkMode : styles.lightMode
}`}
>
<button
onClick={toggleDarkMode}
aria-label="Dark mode toggle"
className={styles.buttonTheme}
type="button"
>
Toggle Theme
</button>
<h1>Headline</h1>
<section className={styles.section}>
<h2>Section</h2>
<p>
This solution toggles CSS root values for font and background colours.
</p>
<p>If light we use:</p>
<p>--fontColor: black; --bgColor: white;</p>
<p>If dark we use:</p>
<p>--fontColor: white; --bgColor: black;</p>
<p>
Better solutions would also take account of the users preferences. You
can see from this{" "}
<a href="https://blog.logrocket.com/dark-mode-react-in-depth-guide/#using-system-settings">
article
</a>{" "}
how you need to access the system settings with media queries.
</p>
</section>
</div>
);
};
export default Solution;
Styling
.lightMode {
--fontColor: black;
--bgColor: white;
}
.darkMode {
--fontColor: white;
--bgColor: black;
}
.buttonTheme {
color: var(--fontColor);
padding: 10px;
margin: 10px 0 20px;
background-color: var(--bgColor);
cursor: pointer;
border: 2px solid;
border-color: var(--fontColor);
scale: 1;
transition: scale 0.3s;
}
.buttonTheme:hover {
scale: 1.1;
}
.buttonTheme:active {
scale: 0.9;
}
.container {
padding: 10px;
transition: 0.3s;
color: var(--fontColor);
background-color: var(--bgColor);
}
.section {
max-width: 400px;
margin: 20px 0;
padding: 20px;
border: 1px solid;
border-color: var(--fontColor);
}
.section p {
margin: 0.5rem 0;
}
.section a,
.section a:visited,
.section a:active {
color: inherit;
text-decoration: underline;
}