CSS Variables (also called custom properties) let you define reusable style values directly in CSS using the --name format. They work perfectly with React for building scalable, themeable UIs.
You can define them globally using :root, scope them to specific components, and even update them dynamically at runtime with JavaScript or React code.
In React projects, CSS variables are widely used for themes, colors, spacing, and light/dark modes.
-- prefix.:root to be available everywhere.var(): Access variable values using var(--name)..module.css files.Declaring CSS Variables:
--variable-name: value;.:root so they cascade across the whole document.Using CSS Variables:
var() function to read values: color: var(--text-color);color: var(--text-color, #333);Local vs Global Behavior:
Define a theme in styles.css and use it in a React App component.
// Define global theme variables
/* styles.css */
:root {
--primary-color: #007bff;
--secondary-color: #6c757d;
--text-color: #333;
--padding: 10px;
}
.button {
background-color: var(--primary-color);
color: white;
padding: var(--padding);
border: none;
border-radius: 4px;
}
// Basic React component using the CSS variables
// App.js
import React from "react";
import "./styles.css";
function App() {
return (
<div className="text-center mt-4">
<button className="button">Click Me</button>
</div>
);
}
export default App;
Use a local variable --card-bg and override it when a .dark class is applied.
// Card styles with local CSS variable overrides
/* Card.css */
.card {
--card-bg: #ffffff;
background-color: var(--card-bg);
border-radius: 8px;
padding: 20px;
}
.card.dark {
--card-bg: #1c1c1c;
color: white;
}
// Toggle local CSS variable by switching class
// Card.js
import React, { useState } from "react";
import "./Card.css";
function Card() {
const [dark, setDark] = useState(false);
return (
<div className={`card ${dark ? "dark" : ""}`}>
<h4>Themed Card</h4>
<p>This card uses local CSS variable overrides.</p>
<button
className="btn btn-outline-primary"
onClick={() => setDark(!dark)}
>
Toggle Theme
</button>
</div>
);
}
export default Card;
Update --primary-color at runtime using the DOM API to change the theme instantly.
// Dynamically change the CSS variable from React
// DynamicTheme.js
function DynamicTheme() {
const setTheme = (color) => {
document.documentElement.style.setProperty("--primary-color", color);
};
return (
<div className="text-center mt-4">
<button
className="btn btn-primary me-2"
onClick={() => setTheme("#007bff")}
>
Blue
</button>
<button
className="btn btn-success me-2"
onClick={() => setTheme("#28a745")}
>
Green
</button>
<button
className="btn btn-danger"
onClick={() => setTheme("#dc3545")}
>
Red
</button>
<div className="mt-3">
<button className="button">Dynamic Themed Button</button>
</div>
</div>
);
}
export default DynamicTheme;
Use CSS variables inside .module.css files and override them with different module classes.
// Scoped variables inside a CSS Module
/* ThemeCard.module.css */
.card {
--theme-bg: #f8f9fa;
--theme-color: #333;
background-color: var(--theme-bg);
color: var(--theme-color);
padding: 15px;
border-radius: 8px;
}
.cardDark {
--theme-bg: #333;
--theme-color: #fff;
}
// Combine module classes to override variables
// ThemeCard.js
import React, { useState } from "react";
import styles from "./ThemeCard.module.css";
function ThemeCard() {
const [dark, setDark] = useState(false);
return (
<div className={`${styles.card} ${dark ? styles.cardDark : ""}`}>
<h5>CSS Variables with Modules</h5>
<p>Switch theme using CSS variable overrides.</p>
<button
className="btn btn-outline-secondary"
onClick={() => setDark(!dark)}
>
Toggle Mode
</button>
</div>
);
}
export default ThemeCard;
In the examples above:
--primary-color. Changing the variable updates all buttons using it.--card-bg. When the .dark class is applied, the value is overridden only for that card.--primary-color on document.documentElement, so any element using that variable updates immediately.styles.card and styles.cardDark.This pattern is perfect for building theme systems, especially when combined with React state and context.
:root so you can manage them from a single place.--primary-bg, --text-color, and --border-radius instead of --blue or --nice-color.transition properties (e.g., background-color 0.3s ease) to create smooth theme animations.:root with variables for primary/secondary colors, text color, and base spacing.data-theme attribute and updates CSS variables using setProperty()..module.css and use local CSS variables to override part of the global theme.background-color, color) to make the switch feel polished.Goal: Learn how to define, use, and update CSS variables in React so you can build scalable, easily themeable user interfaces.