Blog>
Snippets

Dynamic Theming with CSS Variables in Next.js

Show how to use CSS custom properties (variables) within a Next.js application to allow dynamic theming.
// pages/_app.js
import '../styles/globals.css';

function MyApp({ Component, pageProps }) {
  return <Component {...pageProps} />
}

export default MyApp;
This is the custom App component (_app.js) where you can include global CSS for the Next.js application.
// styles/globals.css
:root {
  --primary-color: #0070f3;
  --background-color: #fff;
  --text-color: #333;
}

[data-theme='dark'] {
  --primary-color: #9e9e9e;
  --background-color: #000;
  --text-color: #fff;
}

body {
  background-color: var(--background-color);
  color: var(--text-color);
}
In the globals.css file, CSS variables are set for the default light theme. A dark theme is also defined using a data attribute selector where variables are reassigned different values.
// components/ToggleThemeButton.js
import { useState, useEffect } from 'react';

const ToggleThemeButton = () => {
  const [theme, setTheme] = useState('light');

  useEffect(() => {
    document.documentElement.setAttribute('data-theme', theme);
  }, [theme]);

  const toggleTheme = () => {
    setTheme(theme === 'light' ? 'dark' : 'light');
  };

  return (
    <button onClick={toggleTheme}>
      Toggle Theme
    </button>
  );
};

export default ToggleThemeButton;
This component, ToggleThemeButton.js, includes a button that allows the user to toggle the theme. The useEffect hook updates the `data-theme` attribute on the document's root element whenever the theme state changes, causing a re-render with the new theme variables.
// pages/index.js
import ToggleThemeButton from '../components/ToggleThemeButton';

export default function Home() {
  return (
    <div>
      <h1>Welcome to Next.js!</h1>
      <ToggleThemeButton />
    </div>
  );
}
In the main page component (pages/index.js), the ToggleThemeButton component is imported and used to render a button that lets the user toggle between light and dark themes.