Dynamic Theming in React with CSS Variables
Unlock the Power of Dynamic Themes with Custom CSS Variables in React
Jun 25, 2024 - 13:43 • 4 min read
In the ever-evolving world of web development, creating a seamless user experience is of paramount importance. One effective way to enhance user experience is by enabling dynamic theming. In this blog post, we"ll dive deep into how you can leverage CSS variables in React to create dynamic, responsive, and user-friendly themes.
The Essence of Dynamic Theming
Dynamic theming allows users to switch themes on the fly without needing a page refresh. It is particularly useful for implementing light and dark modes, different user preferences, or custom brand themes.
Traditional CSS theming often involves using separate CSS files or frameworks like SCSS. However, the advent of CSS variables (custom properties) has revolutionized the way we handle dynamic theming.
Why CSS Variables?
CSS variables offer several advantages:
- Dynamic Updates: They can change at runtime, making real-time theming possible.
- Global Scope: Defined variables can be reused throughout your application.
- Flexibility: Easier integration with JavaScript.
With these benefits, CSS variables are a perfect fit for dynamic theming in React.
Setting Up CSS Variables
Let"s start by defining a basic CSS variable setup. In your index.css
or App.css
, specify the variables for different theme properties.
:root {
--primary-color: #6200ee;
--secondary-color: #03dac6;
--background-color: #ffffff;
--text-color: #000000;
}
[data-theme="dark"] {
--primary-color: #bb86fc;
--secondary-color: #03dac6;
--background-color: #121212;
--text-color: #ffffff;
}
In the above code, :root
defines the default theme, while [data-theme="dark"]
defines the dark mode theme.
Integrating CSS Variables with React
To switch themes dynamically in React, we will create a ThemeContext
. This context will handle the current theme state and provide a method to toggle the theme.
import React, { createContext, useState, useContext } from "react";
const ThemeContext = createContext();
export const ThemeProvider = ({ children }) => {
const [theme, setTheme] = useState("light");
const toggleTheme = () => {
const newTheme = theme === "light" ? "dark" : "light";
setTheme(newTheme);
document.documentElement.setAttribute("data-theme", newTheme);
};
return (
<ThemeContext.Provider value={{ theme, toggleTheme }}>
{children}
</ThemeContext.Provider>
);
};
export const useTheme = () => useContext(ThemeContext);
In this code, the ThemeProvider
component manages the theme state and updates the data-theme
attribute on the document root when the theme is toggled.
Utilizing the Theme Context
Now, let"s create a simple app that uses our ThemeProvider
to toggle between light and dark themes.
import React from "react";
import { ThemeProvider, useTheme } from "./ThemeContext";
const App = () => {
const { theme, toggleTheme } = useTheme();
return (
<div className="App">
<h1>Current Theme: {theme}</h1>
<button onClick={toggleTheme}>Toggle Theme</button>
</div>
);
};
export default function Root() {
return (
<ThemeProvider>
<App />
</ThemeProvider>
);
}
In this example, the App
component consumes the useTheme
hook to access the current theme and the toggleTheme
function.
Advanced Theming with theming Libraries
For more sophisticated theming features, consider integrating with popular libraries like styled-components
or emotion
. These libraries provide advanced capabilities for managing and applying themes dynamically.
styled-components
Using import styled, { ThemeProvider } from 'styled-components';
const lightTheme = {
primary: '#6200ee',
secondary: '#03dac6',
background: '#ffffff',
text: '#000000'
};
const darkTheme = {
primary: '#bb86fc',
secondary: '#03dac6',
background: '#121212',
text: '#ffffff'
};
const themes = { light: lightTheme, dark: darkTheme };
const ThemeSwitcher = () => {
const { theme, toggleTheme } = useTheme();
return (
<button onClick={toggleTheme}>Switch to {theme === 'light' ? 'dark' : 'light'} theme</button>
);
};
const AppContainer = styled.div`
background-color: ${props => props.theme.background};
color: ${props => props.theme.text};
`;
const App = () => {
const { theme } = useTheme();
return (
<ThemeProvider theme={themes[theme]}>
<AppContainer>
<h1>Theme: {theme}</h1>
<ThemeSwitcher />
</AppContainer>
</ThemeProvider>
);
};
Conclusion
Dynamic theming can significantly elevate user experience, providing personalized and accessible options. Leveraging CSS variables in conjunction with React allows for creating flexible and maintainable theme systems. By abstracting theming logic through context or popular libraries, you can manage theme states more efficiently and ensure a seamless user experience.
Happy theming!