CSS Custom Properties
Add Variables to Your CSS
A presentation at JavaScript Meetup Luxembourg in May 2018 in Luxembourg by Geoffrey Crofte
Add Variables to Your CSS
UX/UI Web Designer at Maltem (Foyer)
You can follow me on Twitter, my personal website and my blog, CreativeJuiz.
Overview
What are Custom Properties? So first, let’s try do define what is a custom properties.
And please, everybody call them CSS Variables :) You should do so.
$color: #bada55; @color: #bada55;
This presentation is not about Sass or LESS variables. CSS Variables have nothing to do with Sass or LESS variables.
This is more about something like the f irst CSS variable you might already know(?) currentColor. This variable comes directly f rom the SVG specif ication and perfectly works in HTML. In this example the colour of the text and borders depends on the current def ined color.
http: //bit.ly/csscurrentcolor
I change the value of colour property and tadaaaa Magic happens. But…
This is not about currenColor neither or any predefined CSS variables, it’s about Custom Variables. To better understand Custom Properties, I spent free hours in the documentation. So, I did.
A custom property is any property whose name starts with two dashes […] like --foo
This is one of the first description of a CustomProperty by The W3C. Really helpful, kinda like it… do you? Don’t worry, there are more helpful words later…
Custom properties are solely for use by authors and users; CSS will never give them a meaning beyond what is presented here. Or not…
But THAT, is a teaser. In fact, absolutely not. The very first time you really read the word “Variable” is inside an example of the documentation.
Right here. “Custom properties def ine variables”… yay. All of that to say: custom properties are in fact variables for CSS.
Joke behind us, let summarize the documentation, in some words. 2) …you can get a variable with that function, 3) …you have to know that, 4) …I mean, really, you’ll see.
In other words, do the fuuuuck you want with them, if it’s not understandable by the CSS engine of your browser, the return value will be a silent error.
How to use CSS Variables? Let’s go with some code examples to better understand the syntax.
-- variableName :
value ; CSS Declaration :root { } First you need to declare it. I used :root pseudo element that refers to the HTML element for web page, or SVG element for SVG document, for example. It’s a way to declare a variable globally. You might be thinking why a double dash? Remember the pref ixed properties -moz- to address a custom property to a specif ic browser. It’s the same idea but with an empty pref ix to address all the browsers.
-- variableName :
value ; CSS Declaration .element { } Another way to declare variable is locally. Here inside an .element declaration. The value of this variable will be available only for this element and its children, and the children of its children.
property:
variableName ) ; .element { } CSS Use Then you can get the value of your variable with the var() function.
Quick Example of use Here a sample of code. Declare link color in root, Use var() function to get the colour value, and that’s all, you know everything about CSS Variables, thanks for coming :D
Why CSS instead of Sass Variables? Ok. Kidding. Now you might be thinking why? “I can do the same with Sass variables”. Yep, you’re right, but not really.
The main issue with Sass (or LESS) variables: They have to be computed to get their value. Computation The main issue with Sass is that Sass has to be computed to generate CSS, and sometimes computation leads to a big amount of code. Right?
CSS Variables are alive CSS Variables are alive, they are not computed. Here I will change one CSS variable declared at the root level. And the magic happens. It’s something really useful when it comes the moment of debugging things. Editing variables f rom the dev tool is a real time saver. You can’t do that with Sass.
JavaScript can access them JavaScript can access them, edit them or set theme quite easily. JavaScript can’t access Sass variables.
Media Queries ❤ CSS Variables Imagine a website you build with a global margin and padding of f ifteen pixels. When your screen is big enough, you increase the margins to forty pixels. 1) With Sass you would probably have to do something like that. Or perhaps by using mixins, which is way more complex. 2) With CSS Variables, you can do something like that.
Media Queries ❤ CSS Variables Imagine a website you build with a global margin and padding of f ifteen pixels. When your screen is big enough, you increase the margins to forty pixels. 1) With Sass you would probably have to do something like that. Or perhaps by using mixins, which is way more complex. 2) With CSS Variables, you can do something like that.
CSS Variables are inherited CSS variables are inherited. Let’s see that with this little dirty demo. Let’s say I have one link alone, and 2 links inside a nav element. 1) I declare a link variable with purple value. Nothing happens, yet. 2) I declared a color by default for links with my variable as value. What will happen? All the links turn purple. 3) Then I declare a new value for my variable inside a new declaration, and I target links into my nav element. What will happen? Only nav links turn salmon. 4) And now? See? I just removed “a” f rom my last declaration. What will happen? Nothing happens. Links inside nav are still salmon because custom properties are inherited.
CSS Variables are inherited CSS variables are inherited. Let’s see that with this little dirty demo. Let’s say I have one link alone, and 2 links inside a nav element. 1) I declare a link variable with purple value. Nothing happens, yet. 2) I declared a color by default for links with my variable as value. What will happen? All the links turn purple. 3) Then I declare a new value for my variable inside a new declaration, and I target links into my nav element. What will happen? Only nav links turn salmon. 4) And now? See? I just removed “a” f rom my last declaration. What will happen? Nothing happens. Links inside nav are still salmon because custom properties are inherited.
CSS Variables are inherited CSS variables are inherited. Let’s see that with this little dirty demo. Let’s say I have one link alone, and 2 links inside a nav element. 1) I declare a link variable with purple value. Nothing happens, yet. 2) I declared a color by default for links with my variable as value. What will happen? All the links turn purple. 3) Then I declare a new value for my variable inside a new declaration, and I target links into my nav element. What will happen? Only nav links turn salmon. 4) And now? See? I just removed “a” f rom my last declaration. What will happen? Nothing happens. Links inside nav are still salmon because custom properties are inherited.
CSS Variables are inherited CSS variables are inherited. Let’s see that with this little dirty demo. Let’s say I have one link alone, and 2 links inside a nav element. 1) I declare a link variable with purple value. Nothing happens, yet. 2) I declared a color by default for links with my variable as value. What will happen? All the links turn purple. 3) Then I declare a new value for my variable inside a new declaration, and I target links into my nav element. What will happen? Only nav links turn salmon. 4) And now? See? I just removed “a” f rom my last declaration. What will happen? Nothing happens. Links inside nav are still salmon because custom properties are inherited.
CSS Variables are inherited CSS variables are inherited. Let’s see that with this little dirty demo. Let’s say I have one link alone, and 2 links inside a nav element. 1) I declare a link variable with purple value. Nothing happens, yet. 2) I declared a color by default for links with my variable as value. What will happen? All the links turn purple. 3) Then I declare a new value for my variable inside a new declaration, and I target links into my nav element. What will happen? Only nav links turn salmon. 4) And now? See? I just removed “a” f rom my last declaration. What will happen? Nothing happens. Links inside nav are still salmon because custom properties are inherited.
CSS Variables are inherited CSS variables are inherited. Let’s see that with this little dirty demo. Let’s say I have one link alone, and 2 links inside a nav element. 1) I declare a link variable with purple value. Nothing happens, yet. 2) I declared a color by default for links with my variable as value. What will happen? All the links turn purple. 3) Then I declare a new value for my variable inside a new declaration, and I target links into my nav element. What will happen? Only nav links turn salmon. 4) And now? See? I just removed “a” f rom my last declaration. What will happen? Nothing happens. Links inside nav are still salmon because custom properties are inherited.
Demos & Use Cases Let’s go with some use cases and demos.
http: //bit.ly/cssvargradient The f irst demo is for the Wahoo effect. It’s a pointer tracking effect where positioning if done with CSS and…
Mouse position …and 6 lines of JS. Sorry if I disappoint you, but that’s all for JS.
CSS Transformation And… yeah sorry CSS can be really verbose sometimes. So here, the 3 things you have to see are… 1) I’m setting up 2 variables I need to position my halo 2) Then I position the element with a simple calculation, 3) Finally, the interesting part, I transform my element by translating it using variables declared with JS. The size of the pseudo-element is equal to zero at this point. ok?
CSS Transformation And… yeah sorry CSS can be really verbose sometimes. So here, the 3 things you have to see are… 1) I’m setting up 2 variables I need to position my halo 2) Then I position the element with a simple calculation, 3) Finally, the interesting part, I transform my element by translating it using variables declared with JS. The size of the pseudo-element is equal to zero at this point. ok?
CSS Transformation And… yeah sorry CSS can be really verbose sometimes. So here, the 3 things you have to see are… 1) I’m setting up 2 variables I need to position my halo 2) Then I position the element with a simple calculation, 3) Finally, the interesting part, I transform my element by translating it using variables declared with JS. The size of the pseudo-element is equal to zero at this point. ok?
CSS Transformation And… yeah sorry CSS can be really verbose sometimes. So here, the 3 things you have to see are… 1) I’m setting up 2 variables I need to position my halo 2) Then I position the element with a simple calculation, 3) Finally, the interesting part, I transform my element by translating it using variables declared with JS. The size of the pseudo-element is equal to zero at this point. ok?
CSS Transformation And when the user starts hovering the element, we give it a real size.
CSS Transformation And when the user starts hovering the element, we give it a real size.
CSS Transformation And when the user starts hovering the element, we give it a real size.
Why not pushing transformations directly in JavaScript? Now you’re wondering… So f inally, why not pushing transformations directly in JavaScript? Yeah, right, why not? This code is perfectly functional. 1) You will have to maintain styles inside JS. This is not the purpose of JS, and in an era of Design System, it’s a lack of portability. 2) Even declared in JS, CSS variables are inherited, (in that case we don’t really care, I agree) 3) It’s simply a philosophy, CSS is for styling, JS is not, 4) It’s Futur proof, let the CSS engine handle that part. Just send CSS variable values to CSS with JS, that’s all.
Why not pushing transformations directly in JavaScript? Now you’re wondering… Maintainability / Portability style=“transform…” is dirty. Period. So f inally, why not pushing transformations directly in JavaScript? Yeah, right, why not? This code is perfectly functional. 1) You will have to maintain styles inside JS. This is not the purpose of JS, and in an era of Design System, it’s a lack of portability. 2) Even declared in JS, CSS variables are inherited, (in that case we don’t really care, I agree) 3) It’s simply a philosophy, CSS is for styling, JS is not, 4) It’s Futur proof, let the CSS engine handle that part. Just send CSS variable values to CSS with JS, that’s all.
Why not pushing transformations directly in JavaScript? Now you’re wondering… Maintainability / Portability style=“transform…” is dirty. Period. Inheritance style=“transform…” do not make --x and --y inherited. So f inally, why not pushing transformations directly in JavaScript? Yeah, right, why not? This code is perfectly functional. 1) You will have to maintain styles inside JS. This is not the purpose of JS, and in an era of Design System, it’s a lack of portability. 2) Even declared in JS, CSS variables are inherited, (in that case we don’t really care, I agree) 3) It’s simply a philosophy, CSS is for styling, JS is not, 4) It’s Futur proof, let the CSS engine handle that part. Just send CSS variable values to CSS with JS, that’s all.
Why not pushing transformations directly in JavaScript? Now you’re wondering… Maintainability / Portability style=“transform…” is dirty. Period. Inheritance style=“transform…” do not make --x and --y inherited. It’s a philosophy CSS is for styling. JS is not. So f inally, why not pushing transformations directly in JavaScript? Yeah, right, why not? This code is perfectly functional. 1) You will have to maintain styles inside JS. This is not the purpose of JS, and in an era of Design System, it’s a lack of portability. 2) Even declared in JS, CSS variables are inherited, (in that case we don’t really care, I agree) 3) It’s simply a philosophy, CSS is for styling, JS is not, 4) It’s Futur proof, let the CSS engine handle that part. Just send CSS variable values to CSS with JS, that’s all.
Why not pushing transformations directly in JavaScript? Now you’re wondering… Maintainability / Portability style=“transform…” is dirty. Period. Inheritance style=“transform…” do not make --x and --y inherited. It’s a philosophy CSS is for styling. JS is not. Futur proof Let the CSS engine handle that part. So f inally, why not pushing transformations directly in JavaScript? Yeah, right, why not? This code is perfectly functional. 1) You will have to maintain styles inside JS. This is not the purpose of JS, and in an era of Design System, it’s a lack of portability. 2) Even declared in JS, CSS variables are inherited, (in that case we don’t really care, I agree) 3) It’s simply a philosophy, CSS is for styling, JS is not, 4) It’s Futur proof, let the CSS engine handle that part. Just send CSS variable values to CSS with JS, that’s all.
http: //bit.ly/cssvargradient2 A little demonstration with the same principle but applied to a dynamic gradient color on a text.
CSS Transformation The JavaScript code is quite the same than previously, but I only need the X value. I applied the transformation directly inside the linear-gradient. The position of each colour in that gradient is calculated thanks to the calc() function and a little modif ier. That’s all. The rest are the properties to apply gradient to text.
Themable interfaces Another good way to use CSS variables is when it comes the time to create variation of components. Imagine a bunch of elements like titles, texts and buttons. Usual, right?
Themable interfaces Another good way to use CSS variables is when it comes the time to create variation of components. Imagine a bunch of elements like titles, texts and buttons. Usual, right?
Themable interfaces To do that, you can do it the old overflowing fashion way. With a lot of duplicated code. 1) Or you can use CSS variables to declare a bunch of initial variables: 2) Then change only what your need for your variation.
Themable interfaces To do that, you can do it the old overflowing fashion way. With a lot of duplicated code. 1) Or you can use CSS variables to declare a bunch of initial variables: 2) Then change only what your need for your variation.
Themable interfaces To do that, you can do it the old overflowing fashion way. With a lot of duplicated code. 1) Or you can use CSS variables to declare a bunch of initial variables: 2) Then change only what your need for your variation.
Accessibility Example With the same principle, you can create alternate Stylesheets to load only when it’s needed.
Accessibility Example You just need to set a class on the root element or load a specif ic stylesheet with redef ined variables.
Responsive Again with the same principle, all the responsive work is now easier.
Responsive Again with the same principle, all the responsive work is now easier.
Further Takeaways Now you know more CSS Variables, let’s go further with a few tips.
-- variableName : value !important ; :root { } CSS Variables are CSS properties CSS Variables are actual CSS properties, they are ruled by the same principles. So yeah, if you need to override a value for sure, you can also use !important.
-- variableName : lolilol; :root { } (kind of) Silent error If you set a non-CSS-compatible value for you property, CSS will fallback to a silent error. A non valid value makes var() function return a new type of error.
-- spacing : 20 ; :root { } You can’t “build up” values. margin : var(--spacing) px ; :root { } Doesn’t work You cannot build up values with separate numbers and units.
spacing :
; :root { } Invalid Valid Yeah, that’s a space caracter. The f irst variable is invalid. The second is valid, it’s equal to a “space” caracter value. Don’t ask.
variableName, default ) ; You can add a parameter which provides a fallback if variableName is not def ined, “default” value will be used instead.
Fallback value A little exercise for you, ready? 1) What happens if my browser doesn’t support CSS Variables? Purple happens. 2) What happens if my variable if not set? Salmon, my fallback happens. 3) If I set my variable, you get the right color. 4) What if the variable value is invalid? Like 5 degrees. var() fallback to the initial value, which is none-transparent for background. The real error for the CSS engine is “Invalid at computed value time”.
Fallback value Doesn’t support var() A little exercise for you, ready? 1) What happens if my browser doesn’t support CSS Variables? Purple happens. 2) What happens if my variable if not set? Salmon, my fallback happens. 3) If I set my variable, you get the right color. 4) What if the variable value is invalid? Like 5 degrees. var() fallback to the initial value, which is none-transparent for background. The real error for the CSS engine is “Invalid at computed value time”.
Fallback value Doesn’t support var() Fallback is there A little exercise for you, ready? 1) What happens if my browser doesn’t support CSS Variables? Purple happens. 2) What happens if my variable if not set? Salmon, my fallback happens. 3) If I set my variable, you get the right color. 4) What if the variable value is invalid? Like 5 degrees. var() fallback to the initial value, which is none-transparent for background. The real error for the CSS engine is “Invalid at computed value time”.
Fallback value Doesn’t support var() Fallback is there A little exercise for you, ready? 1) What happens if my browser doesn’t support CSS Variables? Purple happens. 2) What happens if my variable if not set? Salmon, my fallback happens. 3) If I set my variable, you get the right color. 4) What if the variable value is invalid? Like 5 degrees. var() fallback to the initial value, which is none-transparent for background. The real error for the CSS engine is “Invalid at computed value time”.
Fallback value Doesn’t support var() Fallback is there --bgColor Value A little exercise for you, ready? 1) What happens if my browser doesn’t support CSS Variables? Purple happens. 2) What happens if my variable if not set? Salmon, my fallback happens. 3) If I set my variable, you get the right color. 4) What if the variable value is invalid? Like 5 degrees. var() fallback to the initial value, which is none-transparent for background. The real error for the CSS engine is “Invalid at computed value time”.
Fallback value Doesn’t support var() Fallback is there --bgColor Value A little exercise for you, ready? 1) What happens if my browser doesn’t support CSS Variables? Purple happens. 2) What happens if my variable if not set? Salmon, my fallback happens. 3) If I set my variable, you get the right color. 4) What if the variable value is invalid? Like 5 degrees. var() fallback to the initial value, which is none-transparent for background. The real error for the CSS engine is “Invalid at computed value time”.
Fallback value Doesn’t support var() Fallback is there --bgColor Value Transparent A little exercise for you, ready? 1) What happens if my browser doesn’t support CSS Variables? Purple happens. 2) What happens if my variable if not set? Salmon, my fallback happens. 3) If I set my variable, you get the right color. 4) What if the variable value is invalid? Like 5 degrees. var() fallback to the initial value, which is none-transparent for background. The real error for the CSS engine is “Invalid at computed value time”.
var2, default )) ; You also can have variable as variable fallback.
var5, default ))))) ; So yeah, this is valid and functional.
You can’t cycle with variables Cycle makes the variable invalid. You just cannot do this, CSS is not strong enough :D
You can’t cycle with variables Cycle makes the variable invalid. You just cannot do this, CSS is not strong enough :D
@supports ( color:
) )
{ … } Support Testing And to go further, if you have to support old browsers, you can check the support using @supports
Compatibility CSS Variables are off icially in Candidate Recommandation, and are now supported by almost Eighty Eight percent of users. Depending on your users you should be able to use them on production.
Polyf ills https://github.com/ aaronbarker/css-variables-polyf ill And just in case you need to support Internet Explorer, some people are working on that polyf ill.
“CSS Custom Properties” — @geoff rey_crofte Some resources CSS Variable Secrets (Lea Verou Smashing Conf. 2017) CSS Custom Properties (CCSWG W3C documentation) CSS Mouse Tracking Gradient (Gradient on Text demonstration) CSS Variable Tutorials (A series of 4 short videos about CSS Variables) Here some resources that helped me better understand CSS Variables.
Thanks! And thank you to the Wort for having us.
“CSS Custom Properties” — @geoff rey_crofte Geoff rey Crofte geoffrey.crofte.fr creativejuiz.fr UX/UI Web Designer at Maltem (Foyer) @geoffrey_crofte
55