When working with CSS, you’ve likely encountered the need for variables. CSS custom properties offer a way to implement variables natively in CSS. However, their capabilities extend far beyond simple variable substitution.
CSS custom properties empower you to:
- Define custom property names and assign any value to them.
- Utilize these values within other properties using the
var()function.
While support for CSS custom properties is a bit of a rocky path at the moment and some browsers require specific settings or flags, their adoption is projected to rise significantly. This makes understanding and leveraging them crucial. 1

This article delves into using CSS Custom Properties to enhance the dynamism of your stylesheets, potentially eliminating the need for an extra Sass/LESS step in your workflow.
A Glimpse into CSS’s Limited Variable Support: currentColor
Before exploring CSS custom properties and their dynamic capabilities, it’s important to acknowledge CSS’s existing, albeit limited, variable support through the currentColor keyword. This underutilized yet widely supported variable represents an element’s current color value. Applicable to any declaration accepting a color value, it cascades seamlessly.
Here’s an example:
| |
Beyond cascading, this can also result in:
| |
The primary limitation of currentColor, apart from not being formally defined as a variable in the specification, is its restriction to accepting only color property values, which can pose challenges in certain situations.
Embracing the Power of Fully-fledged CSS Variables
One compelling advantage of CSS pre/postprocessors is their ability to store values within keywords and scope them to specific selectors.
Addressing developers’ longstanding requests, a draft proposing native CSS variables emerged. These variables are formally known as CSS custom properties but are often referred to as CSS variables.
The current specification for native CSS custom properties mirrors the behavior of pre/postprocessor variables. This allows you to store color codes, sizes with various units, or even integers for use as divisors or multipliers.
While the syntax of CSS custom properties might seem unusual compared to other languages, it aligns well within the CSS ecosystem:
| |
You might be wondering about this peculiar “dash-dash” syntax.
Lea Verou, in her insightful talk, CSS Variables: var(–subtitle), offers a clear explanation:
“They function identically to other CSS properties […]. The reason we opted against using a dollar sign or similar symbols is to enable developers to utilize both SASS (or other preprocessor variables) and CSS variables simultaneously. These serve distinct purposes, each with unique capabilities. CSS variables offer functionalities that SASS can’t replicate, and vice versa. Our goal is to facilitate the use of both within the same stylesheet. Think of the dash-dash syntax as a prefix property with an empty prefix.”
The var() function allows us to retrieve custom property values for use anywhere except in selectors, property names, or media query declarations.
Unlike pre/postprocessor variables, which are evaluated during compilation, CSS variables offer dynamic modification even after the stylesheets are compiled. This means they persist as variables in the final CSS.
Let’s illustrate this difference through examples. Consider this SASS code:
| |
After SASS compilation, the resulting CSS looks like this:
| |
As you can see, properties within :root and the media query disappear after compilation. SASS variables can’t exist within a CSS file (or rather, they can be included but are ignored due to invalid CSS syntax), preventing their values from being updated later.
Now, let’s replicate this using CSS variables without any pre/postprocessing:
| |
Since no compilation or transpilation occurs, the code remains unchanged, allowing for dynamic updates to the custom property’s value. Modifying the --value property, for instance using JavaScript, will update its value wherever it’s referenced using the var() function.
The versatility of custom properties extends to tasks like autoprefixing.
Lea Verou demonstrates this using the clip-path property. By setting the desired property’s value to initial with a custom property, each prefixed property can inherit this value:
| |
Subsequently, changing the custom property’s value within a selector becomes straightforward:
| |
For a deeper understanding, refer to Lea’s comprehensive article on autoprefixing with CSS variables.
Ensuring Compatibility with CSS Custom Properties
Given the current state of browser support for CSS Custom Properties, how can we ensure compatibility?
This is where PostCSS and its plugin, postcss-css-variables, come to the rescue.
If you’re unfamiliar with PostCSS, I recommend reading my article “PostCSS: SASS’s New Play Date” to gain a basic understanding of this powerful tool.
Using the postcss-css-variables plugin with the preserve option set to true allows us to retain var() function declarations in the output alongside computed fallback values. It also preserves computed --var declarations. Keep in mind that while custom properties can be updated dynamically after transpilation with this plugin, fallback values remain static unless explicitly targeted and modified.
For a pre/postprocessor-free approach, you can use the CSS @support rule to check for current support and provide suitable fallbacks where necessary:
| |
Dynamic Updates with JavaScript
As previously mentioned, JavaScript can modify CSS variable values. Let’s illustrate this with a light-to-dark theme switch.
Consider this CSS:
| |
Updating the --text-color and --background-color custom properties can be achieved using the following JavaScript:
| |
Exploring Practical Applications
Years of development and discussions surrounding CSS Custom Properties have yielded intriguing use cases:
Theming: Implementing multiple themes, such as light and dark variations, becomes simplified. Toggling between themes involves changing specific custom property values using JavaScript.
Spacing Adjustments: Fine-tuning spacing, like column gutters, across a website can be accomplished by modifying a single CSS variable.
Dynamic calc() Functions: Custom properties enable fully dynamic calc() functions, eliminating the need for complex JavaScript calculations and manual updates.
Revitalizing CSS with Dynamic Power
CSS custom properties introduce a powerful and innovative way to breathe life into stylesheets, bringing dynamic CSS values to the forefront.
With The spec currently under Candidate Recommendation status, standardization is imminent. Now is the perfect time to delve into this feature and harness its full potential.
Note: As Lea Verou pointed on April 22nd, Custom Properties are now supported by default on almost every major browser without the need to switch a flag. Its usage for production is safe unless support for older browsers versions is needed. ↩