Dark theme with Nextjs
Fri, Feb 3, 2023
There are many ways to manage style themes in React and Nextjs, but all of them involve having an array/object with all the styles of each of the different themes.
another way is to use css or scss variables these last ones are in more and more disuse. I, in particular, am going to use css variables and set a default theme in my _document. Why here ?
Because _document runs on server not like _app which runs on client and if you use a useEffect to set your default theme or detect the one the user has on their operating system,
in the time it takes to do this check and add it, there can be a flicker in the page styles. That can be strange.
I did it like this:
1 - css variables
--white-color: 255, 255, 255;
--color-available-arrow: 95, 91 98;
--blog-header: 53, 45, 55;
--blog-nav: 204, 202, 219;
--blog-header: 255, 255, 255;
2 - Set default theme
const Document = (props: Props) => {
<Html lang={props.__NEXT_DATA__.locale} data-theme="light">
3 - Custom hook to change theme
import React from 'react';
const useDarkMode = (): { theme: null | 'dark' | 'light'; toggleTheme: () => void; scheme: typeof scheme } => {
const [theme, setTheme] = React.useState<null | 'dark' | 'light'>(null);
if (typeof window !== 'undefined' && window.matchMedia) {
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
const handler = (event: MediaQueryListEvent) => {
setTheme(event.matches ? scheme.dark : scheme.light);
mediaQuery.addEventListener('change', handler);
return () => mediaQuery.removeEventListener('change', handler);
if (typeof window !== 'undefined' && theme) {
document.documentElement.setAttribute('data-theme', theme);
const toggleTheme = () => {
setTheme(theme === scheme.dark ? scheme.light : scheme.dark);
return { theme, scheme, toggleTheme };
export default useDarkMode;
4 - Using the hook
const { formatMessage: f } = useIntl();
<div className={styles.container}>
<section className={styles.confg}>
alt={f({ id: 'settings.langAlt' })}
name={f({ id: theme === dark ? 'settings.dark' : 'settings.light' })}
<section className={styles.confg}></section>
To do the live test, you can change the theme on your operating system and you will see that my website updates automatically or you can also go to my settings page and change the theme.
All the code in my github repository, if you like this project, or if the content has helped you in any way you can reward me with a ⭐️, Thanks!