eMoosavi
Weekly frontend dev braindumps
Dynamic Theming in React with CSS Variables
React Components

Dynamic Theming in React with CSS Variables

Unlock the Power of Dynamic Themes with Custom CSS Variables in React

Jun 25, 2024 - 13:434 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:

  1. Dynamic Updates: They can change at runtime, making real-time theming possible.
  2. Global Scope: Defined variables can be reused throughout your application.
  3. 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.

Using styled-components

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!

Article tags
reactcssdynamic-themingreact-componentscss-variables
Next article

Advanced JavaScript

Harnessing TypeScript's Power with Advanced Utility Types in React