One of the key aspects of building a polished and professional application is consistent theming. Theming allows you to define a visual identity for your application, controlling elements like colors, typography, spacing, and component styles. In Next.js, you have several powerful options for implementing theming, ranging from simple CSS variables to sophisticated libraries.
We'll explore common approaches to theming in Next.js, focusing on how to create a scalable and maintainable styling system.
CSS variables are a fundamental and highly effective way to manage themes. You can define your theme variables globally (e.g., in _app.js or a global CSS file) and then use them throughout your application. This makes it incredibly easy to change your theme by updating a few variables in one place.
/* styles/globals.css */
:root {
--primary-color: #0070f3;
--secondary-color: #18a0fb;
--background-color: #ffffff;
--text-color: #333333;
--font-family: 'Inter', sans-serif;
--spacing-unit: 8px;
}
[data-theme='dark'] {
--primary-color: #00c4b3;
--secondary-color: #2de6d4;
--background-color: #1e1e1e;
--text-color: #f0f0f0;
}
body {
background-color: var(--background-color);
color: var(--text-color);
font-family: var(--font-family);
}
h1 {
color: var(--primary-color);
}
button {
background-color: var(--primary-color);
color: white;
padding: var(--spacing-unit) calc(var(--spacing-unit) * 2);
border: none;
cursor: pointer;
}// pages/_app.js
import '../styles/globals.css';
function MyApp({ Component, pageProps }) {
return <Component {...pageProps} />;
}
export default MyApp;To implement theme switching with CSS variables, you can toggle a class or data attribute on the <body> or <html> element. This can be managed with React state and context.
import { useState, useEffect, createContext, useContext } from 'react';
const ThemeContext = createContext();
export const ThemeProvider = ({ children }) => {
const [theme, setTheme] = useState('light'); // 'light' or 'dark'
useEffect(() => {
document.body.setAttribute('data-theme', theme);
}, [theme]);
const toggleTheme = () => {
setTheme(prevTheme => (prevTheme === 'light' ? 'dark' : 'light'));
};
return (
<ThemeContext.Provider value={{ theme, toggleTheme }}>
{children}
</ThemeContext.Provider>
);
};
export const useTheme = () => useContext(ThemeContext);