CSS Native Variables
by definition:
CSS Variables are entities defined by either authors or users of Web pages to contain specific values throughout a document. They are set by using custom properties and are accessed by using a specific functional notation var().
Ajá so… what’s up with those CSS variables?
CSS variables have two forms:
- variables:
An association between an identifier and a value that can be used in place of regular values.
- custom properties:
Define the value of a given variable.
How to:
- Declaration:
--my-variable-name: value;
- Use:
var(--my-variable-name);
Example:
:root {
/* We set the "custom property" value as brown */
--main-color: brown;
}
.waka {
/* We retrieve the value of --main-color "variable" */
background-color: var(--main-color);
}
.waka2 {
background-color: var(--main-color);
}
On preprocessor variables
You may be thinking:
Hey!, we already have variables using preprocessors like Sass or Less, why should I care about CSS variables?
Yeap, maybe you’re right and sum up that it’s something “new” that isn’t fully supported by all browsers (yet), but this will be something great.
Ok, first I want to explain the limitations of preprocessor variables:
They aren’t live
Sass is unable to define variables or use @extend inside media queries. If you want to do something like:
$width: 100%;
@media (min-width: 30em) {
$width: 50%;
}
.container {
width: $width;
}
This will compile to:
.container {
width: 100%;
}
It will ignore completely the @media query.
They don’t cascade
In Sass, you can scope variables as global, modules or blocks; with CSS there’s a way to scope variables to a DOM element but, as preprocessors don’t run in the browser and don’t know about the markup, they can’t do it.
For example, if you want to modify the overall display of the font, maybe due to some user configuration, through a variable at the <html>
level, maybe you would try something like:
$font-size: 1em;
.use-large-texts {
$font-size: 1.5em;
}
.body {
font-size: $font-size;
}
But, as the @media query, it won’t work because the class definition with the variable and will be ignored by Sass.
They don’t inherit
Consider a situation where you have a DOM element that you want to style based on whatever color happens to be applied to its parent:
.alert { background-color: lightyellow; }
.alert.info { background-color: lightblue; }
.alert.error { background-color: orangered; }
.alert button {
border-color: darken(background-color, 25%);
}
Even thought this example isn’t a valid Sass/CSS, what I’m trying to do is to darken the border-color
of the button based on the parent .alert
element.
This would be extremely handy, being able to run color functions on inherited DOM properties for accessibility reasons like ensuring the text is always readable and sufficiently contrasts with the background color.
They aren’t interoperable
What if you’re using something like PostCSS and you want to use a 3rd party component that is “themeable” with Sass? …
Uh-oh
It’s not possible to share preprocessor variables across different toolsets.
Yeah but, what’s so special about custom properties then?
Well, CSS custom properties operates just like regular CSS properties and they can overcome all the above “limitations” that preprocessor variables can’t (not easily at least).
Also, preprocessors variables are lexically scoped and static after compilation; custom properties are DOM scoped and dynamic.
CSS Custom properties:
- Are dynamic, as:
- they can be modified at runtime.
- they can be updated inside media queries or by adding a new class to the DOM.
- They can be assigned inline, or with a regular CSS declaration with a selector.
- They can be updated or overridden with cascade rules or javascript.
- They’re inheritable, if assigned to a DOM element they get passed to children.
Wrapping Up
I’m not saying preprocessor variables are the devil or that CSS custom properties will deprecate preprocessors, in fact, it will take a while until we see CSS custom properties on production environments.
I think they will cover each others flaws.
Oh, I didn’t even got deeper in the topic with a proper example: this post would have become so huge! I’d rather opted to write another entry with a repository covering all these “limitations” on both CSS Native Variables and CSS Preprocessors Variables. It will be published soon!