Part 26: Switching Themes Dynamically: Implementing a User-Selectable Dark Mode
[Pages] Client-side Functionality

In our previous discussion, we set up CSS variables for light and dark themes. Now, we’re taking this a step further by allowing users to dynamically switch between these themes using a "ThemeSwitch" button. This post will guide you through the process of implementing this feature using React and styled-jsx.
Default to Light Theme
Initially, we want our website to use the light theme by default. This means our default CSS variables should reflect the light theme settings. We will move the dark theme styles to a separate component to apply them conditionally.
Using styled-jsx for Global Styles
In a React application, styled-jsx is a popular way to apply scoped styles to components. However, for our theme switcher, we need these styles to be global. Styled-jsx allows us to apply styles globally using the global property.
Step 1: Create a Dark Theme Component
To manage our dark theme styles efficiently, we'll create a new component named DarkTheme. This component will render the necessary styles for the dark theme.
// components/DarkTheme.js
function DarkTheme() {
return (
<style jsx global>{`
:root {
--background-color: rgb(14, 14, 14);
--link-color: rgb(234, 207, 3);
--text-color: rgb(230, 230, 230);
}
`}</style>
);
}
export default DarkTheme;This component uses styled-jsx to define global CSS variables for the dark theme. These variables will override the default light theme settings when applied.
Step 2: Modify the ThemeSwitch Component
In the ThemeSwitch component, we will manage the theme switching logic using React's state and conditional rendering.
// components/ThemeSwitch.js
import { useState } from 'react';
import DarkTheme from './DarkTheme';
function ThemeSwitch() {
const [darkMode, setDarkMode] = useState(false);
return (
<>
<button onClick={() => setDarkMode(!darkMode)}>
{darkMode ? 'Switch to Light Mode' : 'Switch to Dark Mode'}
</button>
<style jsx>{`
button {
background: none;
border: none;
color: inherit;
cursor: pointer;
}
`}</style>
{darkMode && <DarkTheme />}
</>
);
}
export default ThemeSwitch;Conditional Rendering
State Management: We use a state variable
darkModeinitialized tofalse. This indicates that the light theme is active by default.Button Click Logic: When the button is clicked, the
darkModestate toggles betweentrueandfalse.Apply Dark Theme Conditionally: We use conditional rendering to apply the
DarkThemecomponent only whendarkModeistrue.
Step 3: Update Global Styles
Ensure your globals.css file reflects only the light theme, as the dark theme styles are now managed by the DarkTheme component:
/* styles/globals.css */
:root {
--background-color: white;
--link-color: darkred;
--text-color: black;
}
body {
font-family: Arial, Helvetica, sans-serif;
background-color: var(--background-color);
color: var(--text-color);
}
a {
color: var(--link-color);
text-decoration: none;
}Testing the Implementation
With this setup, the "ThemeSwitch" button dynamically changes the theme when clicked. Inspecting the page elements will show how the CSS variables change according to the active theme, providing a practical debugging method.
Conclusion
By organizing our styles into separate components and using styled-jsx for global theming, we've created a flexible and maintainable theme-switching mechanism. This setup is applicable in any React application, providing a responsive and user-friendly experience. In future updates, we can explore additional features and optimizations for a more robust theming system.
Last updated