Skip to content

CSS Variables

CSS Variables, officially called as Custom Properties, allow you to define reusable values in your CSS. They enable easier maintenance and flexibility by storing values that can be reused throughout your stylesheets. In case of any change required, you can change the variables and it will reflect across the website, making it easier to change the styles. Lets look at how we can achieve this.

CSS variables are declared using the -- prefix, followed by the variable name. They are defined within a CSS rule, and their values can be any valid CSS value, such as colors, dimensions, or even complex values like gradients.

in the below snippet you can see variables defined inside :root, it’s a pseudo-class that targets the highest-level element in the document (usually the html element). declaring variables in :root makes them globally available throughout the stylesheet.

Here we are defining --primary-color variable inside the :root pseudo class , primary-color variable has -- prefix making it a variable.

:root {
--primary-color: #3498db;
--padding: 10px;
--font-stack: "Helvetica, Arial, sans-serif";
}

CSS variables are used by referencing them with the var() function. This function can be used anywhere a CSS value is required.

Var(—variable-name)` function takes the name of the variable and returns its value. In the below snippet, we are accessing the value of variables defined in the root pseudo class.

The var() function can also accept a fallback value, which is used if the variable is not defined. Fallbacks ensure that the CSS will still render even if a variable is missing or not supported. You can see element2 class using var() having a fallback color.

.element {
color: var(--primary-color);
padding: var(--padding);
font-family: var(--font-stack);
}
.element2 {
color: var(--secondary-color, #e74c3c);
}

CSS Variables offer several advantages, especially in large and complex stylesheets where consistency and maintainability are crucial.

CSS variables allow you to define a value once and reuse it throughout your stylesheet. This reduces repetition and ensures consistency. As we discussed before, if you need to change the background color, you only need to update the variable, and the change is reflected across all elements that use it.

:root {
--primary-bg: #f0f0f0;
--secondary-bg: #e0e0e0;
}
.header {
background-color: var(--primary-bg);
}
.footer {
background-color: var(--secondary-bg);
}

CSS variables make it easy to implement themes. These days, we come across lot of websites that use theme-ing in the name of dark and light mode with the click of a toggle.

You can define multiple sets of variables for different themes and switch between them by updating the variable values.

In this example you can see both light and dark theming (basic) added on :root and .dark-theme.

Applying the class to a high-level element like html or body allows the CSS variable overrides to cascade down to all child elements that use those variables.

:root {
--background: #ffffff;
--text-color: #333333;
}
.dark-theme {
--background: #333333;
--text-color: #ffffff;
}
body {
background-color: var(--background);
color: var(--text-color);
}

Applying the .dark-theme class changes the theme by overriding the variable values.

// To switch to dark theme
document.documentElement.classList.add("dark-theme");
// OR document.body.classList.add('dark-theme');
// To switch back to light theme
document.documentElement.classList.remove("dark-theme");
// OR document.body.classList.remove('dark-theme');

CSS variables can be updated within media queries, allowing for responsive design without duplicating code.

In the following snippet, padding changes dynamically based on the screen width, ensuring a responsive design.

:root {
--padding: 20px;
}
@media (max-width: 600px) {
:root {
--padding: 10px;
}
}
.container {
padding: var(--padding);
}

Variables declared in the :root pseudo-class have global scope, meaning they are accessible anywhere in the document.

:root {
--global-color: #2ecc71;
}
h1 {
color: var(--global-color);
}
p {
color: var(--global-color);
}

--global-color is accessible in both the h1 and p elements.

Variables can also be scoped to specific elements. When a variable is defined inside a specific rule, it is only accessible within that rule and its descendants.

The variable --local-color is only available within .container and its children.

.container {
--local-color: #9b59b6;
color: var(--local-color);
}
.container p {
color: var(--local-color);
}
.other-element {
color: var(--global-color); /* Can't access --local-color */
}

Just like normal CSS properties, CSS variables inherit their values from parent elements. If a child element doesn’t define a variable, it will inherit it from its parent.

In this example, .child inherits --color from .parent.

.parent {
--color: #e74c3c;
color: var(--color);
}
.child {
/* Inherits --color from .parent */
background-color: var(--color);
}

Variables can be overridden in a more specific scope. When a variable is redefined within a nested element, it takes precedence over the inherited value.

The .child element uses its own --padding value instead of the inherited one.

.parent {
--padding: 20px;
}
/*Here child class will having padding 10px not the inherited padding value of 20px*/
.child {
--padding: 10px;
padding: var(--padding);
}