Tutorials‎ > ‎

CSS Variables (CSS Custom Properties)

posted Nov 22, 2017, 4:51 AM by Benedictus Jason Reinhart
Tracing way back to early 2000s, theming a website requires additional complex tools and most are not really lightweight, considering internet accessibility back in 2000s. However since Chrome 49 and Firefox 31, we can use the var() function of CSS and define our custom property. This is especially useful for theming and changing styles dynamically.

For example, if you ever used SASS or LESS before, you can define the main color (primary color) and secondary color of a site with their specific variable syntax. They are great, but they are limited and static, meaning after compiling SASS or LESS to CSS files, they cannot be changed anymore until the next compilation. Imagine you can change your site's primary color dynamically without additional libraries, purely supported by the browser.

Reusability and dynamic are the reason why CSS custom property is awesome. For example, we have a primary color of lightsalmon and a secondary color of lightgreen, we can define our CSS like this:
.button-primary {
background: lightsalmon;
}
.button-secondary {
background: lightgreen;
}
.container {
background: lightsalmon;
}
.bg-secondary {
background: lightgreen;
}
.text-primary {
background: lightsalmon;
}
.text-secondary {
background: lightgreen;
}

However, this can break our site if our brand decide to change its primary and secondary color. If we ever have to revamp the color of the site, we have to change every style of our classes, which is a repetitive work and of course, boring. With CSS custom properties, we can do it better like this:
 :root {
--primary-color: lightsalmon;
--secondary-color: lightgreen;
}
.button-primary {
background: var(--primary-color);
}
.button-secondary {
background: var(--secondary-color);
}
.container {
background: var(--primary-color);
}
.bg-secondary {
background: var(--secondary-color);
}
.text-primary {
background: var(--primary-color);
}
.text-secondary {
background: var(--secondary-color);
}

You don't have to define the variables in the :root. It's just the :root in HTML represents the <html> element and is identical to the selector html, except that its specificity is higher. Now maintaining your CSS is easier as the colors are grouped and reused.

Other use case of the custom property is when you want to customize styles in media query. For example, we have a base padding of 15px in desktop resolution for many components:
.container {
padding: 15px;
}
.card {
padding: 15px;
box-shadow: 1px 1px 1px #444;
}
.box {
padding: 15px;
}
.panel {
padding: 15px;
}

@media (max-width: 768px) {
.container {
padding: 10px;
}
.card {
padding: 10px;
}
.box {
padding: 10px;
}
.panel {
padding: 10px;
}
}

Such a repetitive style declaration. With CSS custom property, we can compact the code into:
:root {
--base-padding: 15px;
}
.container {
padding: var(--base-padding);
}
.card {
padding: var(--base-padding);
box-shadow: 1px 1px 1px #444;
}
.box {
padding: var(--base-padding);
}
.panel {
padding: var(--base-padding);
}

@media (max-width: 768px) {
:root {
--base-padding: 10px;
}
}

Very elegant code, maintainable and not repetitive. Want to change the base padding somehow? Just change it in :root. Different base padding in different resolution? Use the media query to change the custom property in :root.
You can also change the custom property in Javascript. For example, if we want to make a button that increases the base padding:
var button = document.getElementById('#button');
var currentPadding = 15;
button.onclick = function() {
var rootStyle = document.documentElement.style;
currentPadding += 2;
rootStyle.setProperty('--base-padding', currentPadding + 'px');
}

CSS custom property also support fallback or default values, which is used whenever you haven't declared the custom property.
:root {
--base-padding: 15px;
}
.container {
padding: var(--base-padding, 1em);
}
.card {
padding: var(--base-padding, 1em);
box-shadow: 1px 1px 1px #444;
}
.box {
padding: var(--base-padding, 1em);
}
.panel {
padding: var(--base-padding, 2em);
}

@media (max-width: 768px) {
:root {
--base-padding: 10px;
}
}
Comments