When CSS is getting DRY
CSS isn’t the prettiest ‘language,’ but it has successfully powered the styling of the web for over 20 years now.
Ohans Emmanuel
One of the most important principles in coding is DRY, don’t repeat yourself. But unfortunately, CSS did not hear about it, and most of the time programmers spread CSS values multiple time and repeating the same color again and again. There are plenty of naming conventions as BEM, SMACSS & OOCSS, and Some CSS preprocessors like SASS but still. Until came to the rescue the CSS
CSS var’s
The syntax is simple, a var declaration must start with “–“, and you use it by the CSS var() function.
:root {
--mainColor: #222;
--otherColor: #ccc;
}
.theBox {
background-color:var(--other-color);
color: var(--mainColor);
}
As all CSS, the names are case sensitive, so theBox is different from TheBox.
CSS Inheritance
CSS variables declaration has the same rules as all the CSS inheritance. You can define global variables on the “:root” CSS pseudo-class that identifies the document.
:root{ --globalVar:red; }// will work everwhere
p { --innerColor:blue; }// will work only within P
div {color: var(--innerColor);}
p {color: var(--innerColor);}
span {color: var(--globalVar);}
<div>
Sone black text
<p>
Some blue text
<span>
Red text
</span>
<p>
<div>
:root { --color:red; }
div { --color:green;}
p { --color:blue; }
a { --color:pink; }
* {color:var(--color);}
I am red root
<div>
I'm green div
<p>
Look at me, I'm the blue P
<a>
Pink! why? God tell me why?
</a>
</p>
</div>
Fallback
The CSS var() function has a second variable for fallback value.
div p a{
--someColor: pink;
}
p {background:var(--someColor, blue);}
a {
// Or just in case:
background: var(--val1,var(--val2,var(--val3,var(--val4,var(--val5,red)))))}
<p>
Since we have inheritance limitation, this will be blue text
<a>
And this will be red
</a>
</p>
Single tokens
It is possible to use CSS variable as a single token. Just be aware that the variable adds a space after the token:
:root {
--size: 1.4
--border: 2.2rem
}
div {
font-size: var(--size)rem; // Invalid value -> font-size:1.4 rem
border: solid var(--size)red; // Will work -> border: solid 2.2rem red
}
There is still an option to use
:root {
--size: 1.4
}
div {
font-size: calc(var(--size) * 1rem); // font-size: 1.4rem
}
Invalid variables
After all the happiness, there is one downside you need to know. The CSS variable validation comes before the CSS variables are placed, this means that you can place invalid values into CSS attributes.
p {
border: solid 1px red;
}
div p {
border: moshe;
}
<div>
<p>since moshe is invalid, the P will
</p>
have the CSS "p" less specific red border
</div>
// vs
*{
--errorColor: moshe;
}
p {
border: solid 1px red;
}
div p {
border:var(--errorColor);
}
<div>
<p>
Because the CSS variables bypass the CSS
validation, the "p" will nave the invalid
"moshe" border, and will display no border.
</p>
</div>
Last words
Unless you are for some reason using some type of atomic CSS approach, never call a red color red, call it by its use
:root {
--redColor: #ce1616; // Something red'ish
--blueColor: blue;
--greenColor: #16ce34; // Something green'ish
}
.title {
...
...
color: var(--redColor);
background: var(--greenColor);
...
...
}
I can promise you that one day the product manager will announce that we change the site layout to new colors, and you will end out having something like this:
:root {
--redColor: #16ce34; // Something green'ish
--blueColor: #ce1616; // Something red'ish
--greenColor: blue;
}
Believe me, I had seen it again and again. Whatever approach you use for the CSS convention, don’t compromise on the Better use the functional naming.
:root {
--textColor: #ce1616; // Something red'ish
--titlesColor: blue;
--mainBackgroundColor: #16ce34; // Something green'ish
}
.title {
...
...
color: var(--textColor);
background: var(--mainBackgroundColor);
...
...
}
Conclusion
Where has the CSS variables been all this time?