Implementing a dark theme is simple and can be done effectively using CSS and JavaScript. Here's a step-by-step guide to make it work perfectly on your website.
1. CSS Variables for Dark Theme
Start by defining CSS variables for the light and dark theme colors. This allows for easy switching between themes.
/* Light theme variables */
--grey-50: #f8fafc;
--grey-900: #0f172a;
--dark-mode-bg-color: #333;
--dark-mode-text-color: #f0f0f0;
--backgroundColor: var(--grey-50);
--textColor: var(--grey-900);
--darkModeTransition: color 0.3s ease-in-out, background-color 0.3s ease-in-out;
body {
background: var(--backgroundColor);
color: var(--textColor);
transition: var(--darkModeTransition);
}
body.dark-theme {
--textColor: var(--dark-mode-text-color);
--backgroundColor: var(--dark-mode-bg-color);
}
Note: Instead of manually updating
colorandbackground-colorproperties, we update the CSS variables directly inbody.dark-theme. This method is much easier because it avoids needing to check through the whole app’s code. We're only changing the variables, making the process more scalable and maintainable.
You can also automatically switch the theme based on the user's system preferences by using a media query (though we’ll do it manually with JavaScript, so this is commented out here):
/* @media (prefers-color-scheme: dark) {
:root {
--textColor: var(--dark-mode-text-color);
--backgroundColor: var(--dark-mode-bg-color);
}
} */
2. JavaScript Logic for Theme Switching
We'll use React and useContext to handle the dark theme logic. Here's the setup:
import { createContext, useContext, useEffect, useState } from 'react';
// Get initial dark mode state based on system preference or localStorage
const getInitialDarkMode = () => {
const prefersDarkMode = window.matchMedia('(prefers-color-scheme:dark)').matches;
const storedDarkMode = localStorage.getItem('darkTheme') === 'true';
if (storedDarkMode === null) {
return prefersDarkMode;
}
return storedDarkMode === 'true';
};
const AppContext = createContext();
export const AppProvider = ({ children }) => {
const [isDarkTheme, setIsDarkTheme] = useState(getInitialDarkMode());
const toggleDarkTheme = () => {
setIsDarkTheme((prev) => {
const newValue = !prev;
localStorage.setItem('darkTheme', newValue);
return newValue;
});
};
useEffect(() => {
document.body.classList.toggle('dark-theme', isDarkTheme);
}, [isDarkTheme]);
return (
<AppContext.Provider value={{ isDarkTheme, toggleDarkTheme }}>
{children}
</AppContext.Provider>
);
};
export const useGlobalContext = () => useContext(AppContext);
3. Dark Mode Toggle Button
Now, let's add a button to toggle between light and dark mode:
import { BsFillSunFill, BsFillMoonFill } from 'react-icons/bs';
import { useGlobalContext } from '../context';
const ThemeToggle = () => {
const { isDarkTheme, toggleDarkTheme } = useGlobalContext();
return (
<section className='toggle-container'>
<button className='dark-toggle' onClick={toggleDarkTheme}>
{isDarkTheme ? (
<BsFillMoonFill className='toggle-icon' />
) : (
<BsFillSunFill className='toggle-icon' />
)}
</button>
</section>
);
};
export default ThemeToggle;
Conclusion
With just a few lines of CSS and JavaScript, you can easily implement a dark theme that adapts to the user's system preferences and provides a seamless transition when toggled. The key is using CSS variables for dynamic styling and React to manage the theme state.
That's it! Now you have a dark mode toggle feature ready for your application. ✨
Top comments (1)