CSS Custom Properties

A presentation at JavaScript Meetup Luxembourg in May 2018 in Luxembourg by Geoffrey Crofte

Slide 1

Slide 1

CSS Custom Properties

Add Variables to Your CSS

Slide 2

Slide 2

Geoffrey Crofte

UX/UI Web Designer at Maltem (Foyer)

  • geoffrey.crofte.fr
  • creativejuiz.fr
  • @geoffrey_crofte

You can follow me on Twitter, my personal website and my blog, CreativeJuiz.

Slide 3

Slide 3

Overview

Overview

  • What are Custom Properties?
  • Quick start with CSS Variables.
  • Why CSS C.P. instead of Sass variables?
  • Use cases & Demos
  • Takeaways

Slide 4

Slide 4

What are Custom Properties?

What are Custom Properties? So first, let’s try do define what is a custom properties.

Slide 5

Slide 5

What are Custom Properties?

And please, everybody call them CSS Variables :) You should do so.

Slide 6

Slide 6

This not about

$color: #bada55; @color: #bada55;

This presentation is not about Sass or LESS variables. CSS Variables have nothing to do with Sass or LESS variables.

Slide 7

Slide 7

This is more about…

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

Slide 8

Slide 8

This is more about magic

I change the value of colour property and tadaaaa Magic happens. But…

Slide 9

Slide 9

But this is not about currentColor neither

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.

Slide 10

Slide 10

Custom Property definition

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…

Slide 11

Slide 11

Custom Property definition

Custom properties are solely for use by authors and users; CSS will never give them a meaning beyond what is presented here. Or not…

Slide 12

Slide 12

Custom Property definition

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.

Slide 13

Slide 13

W3C Definition Extract

Right here. “Custom properties def ine variables”… yay. All of that to say: custom properties are in fact variables for CSS.

Slide 14

Slide 14

What the Spec says…

  • Custom properties define variables
  • Variables are referenced with the var() notation
  • They are Case-Sensitive
  • Their value is “extremely permissive”

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.

Slide 15

Slide 15

In other words…

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.

Slide 16

Slide 16

How to us CSS Variables?

How to use CSS Variables? Let’s go with some code examples to better understand the syntax.

Slide 17

Slide 17

CSS Declaration

-- 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.

Slide 18

Slide 18

CSS Declaration v2

-- 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.

Slide 19

Slide 19

CSS Variable Use

property:

var(

variableName ) ; .element { } CSS Use Then you can get the value of your variable with the var() function.

Slide 20

Slide 20

Quick Example of use

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

Slide 21

Slide 21

Why CSS instead of Sass Variables?

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.

Slide 22

Slide 22

Computation

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?

Slide 23

Slide 23

CSS Variables are alive

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.

Slide 24

Slide 24

JavaScript can access them

JavaScript can access them JavaScript can access them, edit them or set theme quite easily. JavaScript can’t access Sass variables.

Slide 25

Slide 25

Media Queries ❤️ CSS 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.

Slide 26

Slide 26

Media Queries ❤️ CSS 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.

Slide 27

Slide 27

CSS Variables 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.

Slide 28

Slide 28

CSS Variables 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.

Slide 29

Slide 29

CSS Variables 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.

Slide 30

Slide 30

CSS Variables 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.

Slide 31

Slide 31

CSS Variables 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.

Slide 32

Slide 32

CSS Variables 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.

Slide 33

Slide 33

Demos & Use Cases

Demos & Use Cases Let’s go with some use cases and demos.

Slide 34

Slide 34

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…

Slide 35

Slide 35

Mouse position

Mouse position …and 6 lines of JS. Sorry if I disappoint you, but that’s all for JS.

Slide 36

Slide 36

CSS Transformation

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?

Slide 37

Slide 37

CSS Transformation

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?

Slide 38

Slide 38

CSS Transformation

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?

Slide 39

Slide 39

CSS Transformation

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?

Slide 40

Slide 40

CSS Transformation

CSS Transformation And when the user starts hovering the element, we give it a real size.

  1. But instead of doing that, I’ll do that.
  2. Because remember? We had dimensions declared like that.

Slide 41

Slide 41

CSS Transformation

CSS Transformation And when the user starts hovering the element, we give it a real size.

  1. But instead of doing that, I’ll do that.
  2. Because remember? We had dimensions declared like that.

Slide 42

Slide 42

CSS Transformation

CSS Transformation And when the user starts hovering the element, we give it a real size.

  1. But instead of doing that, I’ll do that.
  2. Because remember? We had dimensions declared like that.

Slide 43

Slide 43

Now you're wondering…

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.

Slide 44

Slide 44

Now you're wondering…

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.

Slide 45

Slide 45

Now you're wondering…

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.

Slide 46

Slide 46

Now you're wondering…

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.

Slide 47

Slide 47

Now you're wondering…

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.

Slide 48

Slide 48

Another Wahou demo

http: //bit.ly/cssvargradient2 A little demonstration with the same principle but applied to a dynamic gradient color on a text.

Slide 49

Slide 49

CSS Transformation

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.

Slide 50

Slide 50

Themable interfaces

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?

  1. First you set your “default styles”.
  2. Then you create variations depending on the context. Here a dark background.

Slide 51

Slide 51

Themable interfaces

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?

  1. First you set your “default styles”.
  2. Then you create variations depending on the context. Here a dark background.

Slide 52

Slide 52

Themable interfaces code

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.

Slide 53

Slide 53

Themable interfaces code with variables

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.

Slide 54

Slide 54

Themable interfaces code with variables

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.

Slide 55

Slide 55

Accessibility Example

Accessibility Example With the same principle, you can create alternate Stylesheets to load only when it’s needed.

Slide 56

Slide 56

Accessibility Example

Accessibility Example You just need to set a class on the root element or load a specif ic stylesheet with redef ined variables.

Slide 57

Slide 57

Responsive

Responsive Again with the same principle, all the responsive work is now easier.

  1. Declare your query and change only variables you need to edit.

Slide 58

Slide 58

Responsive

Responsive Again with the same principle, all the responsive work is now easier.

  1. Declare your query and change only variables you need to edit.

Slide 59

Slide 59

CSS Variables are CSS properties

Further Takeaways Now you know more CSS Variables, let’s go further with a few tips.

Slide 60

Slide 60

CSS Variables are CSS properties

-- 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.

Slide 61

Slide 61

(kind of) Silent error

-- 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.

Slide 62

Slide 62

You can't "build up" values

-- 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.

  1. That doesn’t work. 
 The value has to be a single, valid, unambiguous CSS value. It’s because CSS doesn’t have concatenation, concatenation only works with “content” property. I heard of a concatenation function in a next version, later, maybe, but not for now.

Slide 63

Slide 63

Strange behaviour

-- spacing :; :root { } Strange behaviour

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.

Slide 64

Slide 64

Fallbakc value

Fallback value var(

variableName, default ) ; You can add a parameter which provides a fallback if variableName is not def ined, “default” value will be used instead.

Slide 65

Slide 65

Fallback value

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”.

Slide 66

Slide 66

Fallback value

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”.

Slide 67

Slide 67

Fallback value

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”.

Slide 68

Slide 68

Fallback value

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”.

Slide 69

Slide 69

Fallback value

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”.

Slide 70

Slide 70

Fallback value

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”.

Slide 71

Slide 71

Fallback value

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”.

Slide 72

Slide 72

Variable as Fallback

Variable as Fallback var(

var1, var(

var2, default )) ; You also can have variable as variable fallback.

Slide 73

Slide 73

Variable as Fallback

Variable as Fallback var(

var1, var(

var2, var(

var3, var(

var4, var(

var5, default ))))) ; So yeah, this is valid and functional.

Slide 74

Slide 74

You can't cycle with variables

You can’t cycle with variables Cycle makes the variable invalid. You just cannot do this, CSS is not strong enough :D

  1. But you can actually do that, it works.

Slide 75

Slide 75

You can't cycle with variables

You can’t cycle with variables Cycle makes the variable invalid. You just cannot do this, CSS is not strong enough :D

  1. But you can actually do that, it works.

Slide 76

Slide 76

Support Testing

@supports ( color:

var(

) )

{ … } Support Testing And to go further, if you have to support old browsers, you can check the support using @supports

  • You can use any property (not only color)
  • You don’t have to include an actual variable name, you can just use double-dash.

Slide 77

Slide 77

Compatibility and Support

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.

Slide 78

Slide 78

Polyfills

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.

Slide 79

Slide 79

Some resources

“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.

Slide 80

Slide 80

Thanks! And thank you to the Wort for having us.

Slide 81

Slide 81

“CSS Custom Properties” — @geoff rey_crofte Geoff rey Crofte geoffrey.crofte.fr creativejuiz.fr UX/UI Web Designer at Maltem (Foyer) @geoffrey_crofte

55