In CSS, some properties have shorthand. One property that takes separated values. Syntactic sugar, as they say, to make authoring easier. Take transition , which might look something like:

.element { transition: border 0.2s ease-in-out; }

We could have written it like this:

.element { transition-property: border; transition-duration: 0.2s; transition-timing-function: ease-in-out; }

Every “part” of the shorthand value has its own property it maps to. But that’s not true for everything. Take box-shadow :

.element { box-shadow: 0 0 10px #333; }

That’s not shorthand for other properties. There is no box-shadow-color or box-shadow-offset .

That’s where Custom Properties come to save us!

We could set it up like this:

:root { --box-shadow-offset-x: 10px; --box-shadow-offset-y: 2px; --box-shadow-blur: 5px; --box-shadow-spread: 0; --box-shadow-color: #333; } .element { box-shadow: var(--box-shadow-offset-x) var(--box-shadow-offset-y) var(--box-shadow-blur) var(--box-shadow-spread) var(--box-shadow-color); }

A bit verbose, perhaps, but gets the job done.

Now that we’ve done that, remember we get some uniquely cool things:

We can change individual values with JavaScript. Like: document.documentElement.style.setProperty("--box-shadow-color", "green"); Use the cascade, if we need to. If we set --box-shadow-color: blue on any selector more specific than the :root, we’ll override that color.

Fallbacks are possible too, in case the variable isn’t set at all:

.element { box-shadow: var(--box-shadow-offset-x, 0) var(--box-shadow-offset-y, 0) var(--box-shadow-blur, 5px) var(--box-shadow-spread, 0) var(--box-shadow-color, black); }

How about transforms? They are fun because they take a space-separated list of values, so each of them could be a custom property:

:root { --transform_1: scale(2); --transform_2: rotate(10deg); } .element{ transform: var(--transform_1) var(--transform_2); }

What about elements that do have individual properties for their shorthand, but also offer comma-separated multiple values? Another great use-case:

:root { --bgImage: url(basic_map.svg); --image_1_position: 50px 20px; --image_2_position: bottom right; } .element { background: var(--bgImage) no-repeat var(--image_1_position), var(--bgImage) no-repeat var(--image_2_position); }

Or transitions?

:root { --transition_1_property: border; --transition_1_duration: 0.2s; --transition_1_timing_function: ease; --transition_2_property: background; --transition_2_duration: 1s; --transition_2_timing_function: ease-in-out; } .element { transition: var(--transition_1_property) var(--transition_1_duration) var(--transition_1_timing_function), var(--transition_2_property) var(--transition_2_duration) var(--transition_2_timing_function), }

Dan Wilson recently used this kind of thing with animations to show how it’s possible to pause individual animations!

Here’s browser support: