Lesson Description
The "CSS Custom Properties" Lesson is part of the full, CSS Fundamentals course featured in this preview video. Here's what you'd learn in this lesson:
Kevin introduces CSS custom properties, showing how to declare them, often in the root selector, for colors, fonts, and sizes. He explains naming conventions, demonstrates using them consistently, and highlights how they simplify updates and inheritance across a project.
Transcript from the "CSS Custom Properties" Lesson
[00:00:00]
>> Kevin Powell: ---
Now, earlier on I was talking about inheritance, and one of the big advantages of inheritance was being able to change the value on the body and it just went through our entire thing, right? So, I mean, when we did that, we didn't have to worry about, uh, let's do that really quickly here. If I change the color here to 50 with, well, even that, uh, and it was, we're not seeing it because we need it to be a bit brighter, but it goes through and it's inheriting in everywhere.
[00:00:27]
And I don't have to do it on my P selector and my UL selector and OL and all these different things. There's another way that we can also work or another CSS feature that enables us to do this type of thing, uh, but with values that we have to use in multiple places, such as this gold color where I've set it up on there and I've also set it up here, or even this black color where I had to specifically set it on the span.
[00:00:49]
It's annoying when we have to hunt through things if ever we want to make updates to them, and that is called custom properties. Custom properties are, I always think of them as a new CSS feature. They've been around forever now. It's sort of a classic of the newer CSS features. Uh, the way custom properties look is like any other property, but they always start with a double hyphen. So if I come here, I could just create a my custom property.
[00:01:20]
And then I give it whatever value I want, 500 pixels. I don't know why. I give it a value, and that value is linked to that custom property. Does anyone know why they start with double hyphens? Does anyone in the chat know? I'm curious. Or anyone want to venture a guess? And why it's got something to do with CSS's internal variable names? Yeah, that's really close. I mean, basically, yes. Is there anyone in the chat that said anything or anyone else who wants to?
[00:01:52]
It's one of those things where it looks really different just because all of a sudden there's a double hyphen getting thrown around. Parsing, parsing. So Chris was a bit closer in that it's to do with the internal names of things. We don't want naming collisions. You don't want to create a custom property that exists in CSS, then what does the browser do? It also is, you might make something now, my custom property, this doesn't exist in CSS.
[00:02:19]
I can safely use that. And then next year CSS adds a my custom property and there's a naming collision that appears later on. So hyphen hyphen is to prevent any sort of naming collision from the actual properties that exist in CSS. This double hyphen thing started here. It's the only place that it was for a long time. As you continue your adventures into modern CSS, you'll see it a lot more. It's come up, er, it's coming up for anchor positioning and custom media and a few other things where this is going to become a very normal thing where when you're naming things, it's going to start with a double hyphen, again just to prevent the collisions that could happen.
[00:02:59]
Very important: custom properties need to be declared inside a selector. You cannot come here and declare a custom property like that. It's a property. It's a custom one, you're creating it, but it's still a property, so it has to live inside of a selector. Most of the time you're going to see it declared inside the root selector. The root selector is a weird selector. It's a pseudo class. It starts with the double colon, just like the hover, the focus, focus-visible, but it's different.
[00:03:30]
It's not selecting the state of things necessarily, but it's selecting the root of our document. We already saw that with the REM, which was the root M. It's the same thing as using the root selector of HTML. That's the root of our document. It technically could relate differently in the world of SVG because SVG, the SVG element is the root, depending on how and where it's being used. There might be some other places too, but basically anywhere you use them in a CSS file, the root will be your HTML element.
[00:04:04]
Which begs the question, why do we use root and why don't we just use the HTML element? Uh, in the early days, the reason I heard was because this is higher specificity. At first I was like, OK, that makes sense. But then as more time went on, I go, wait, that doesn't actually change anything, because you wouldn't be having it on the root and the HTML element. Uh, but it's sort of become best practice, normal way of doing it.
[00:04:29]
Uh, I, at one point, browsers were optimizing for custom properties that were on your root selector, if they weren't changed. I believe that's still the case, but I don't quote me on that. But there were optimizations that were done, so that was another reason. And it also just creates this sort of selector where you know your custom properties are going to be. You go to a project, if there's custom properties, you know they're on the root, and that's just where they are.
[00:04:51]
It's a standard you're going to see used everywhere, and I like it, so I keep doing it, but I mean you could technically put them on the body or you could put them on any selector you wanted, really, and there are times for locally scoped custom properties that we'll see a little bit later on. Now the benefit of custom properties, I mentioned it a bit. I'm going to jump back to the course website quickly for this one.
[00:05:16]
Uh, just as I have a very fast example here where I'm using a custom property for this avatar. And you can see this case, I didn't do it on the root. I'm doing it just over here, but I'm using that on the border and on this box shadow, and that means if I come here and I change the color in one place, it updates in both of them at the same time. That's really the big benefit of where custom properties come in.
[00:05:39]
This is a small scale benefit because it's only twice, but sometimes you'll have it used in 100 different places. There's another really good benefit is that the name of it, color or whatever you end up calling it, brand color is a lot easier to remember than HSL 207, 50% and the same with font sizes and other things like that. It's super easy to remember a font-size name that you've created versus trying to come up with the specific values that you've had along the way.
[00:06:10]
Other thing that's really important is custom properties are inherited. This is a huge benefit to how they work, just like the typography things. So if you do your brand color all the way out on the HTML element, you can use it on any element within your page without worrying about it, which is super good. We've already talked about what the root is. Uh, as far as common use cases, it's anything that you're repeating a lot.
[00:06:34]
So font sizes, colors, font families, spacing also becomes a very common use case if you have consistent spacing within projects. Uh, it can become very, very useful. And in this case, there's a few things that we could use in our project, so we're going to go and set those up and take a look at why they could be useful while we're doing it. So, I don't want my custom property, we can come in with some better ones.
[00:07:02]
I'm just going to fix the spacing here. So I mentioned colors, so we had two colors. The fun part of custom properties is naming them. I always put a prefix at the beginning of them to say what my custom property is. It makes it a little bit easier just to use it, uh, or, or no, you don't have to do this at all, or you could write it out long. It's you naming it, but naming things is hard. So I need to come up with a name for this.
[00:07:32]
Actually, let's do the other one first. Let's start with this gold color here. A bad name for it would be color gold. And then I take this color, I can put that there, it would work. So let's just put that really fast and then I come down here and I haven't talked about using them yet. So to use a custom property, we come in and say var, open and close curly braces and the name of it, color gold. And it's still working.
[00:08:04]
Why is that a bad name? Anyone want one? Yeah, right. Because if you decide to change the color later, yeah, it's already called gold if you want to change it to blue or something. Yeah, exactly. If all of a sudden, just in VS Code, there's this, which is kind of handy. If ever the main color switches, then the color gold doesn't make much sense. You might even have a light and dark theme and you're, you know, you call it white and then it's no longer white because it's switched to black, and that's really confusing.
[00:08:33]
So, uh, naming things gets a little tricky. For colors, uh, I have a sort of different strategies for each one. For colors, I like using accent if it's something bright, uh, you can have color brand if it's the main brand color, uh, if you have different states, success state, info state, warning states, things like that, those are the types of names I try using. So it's how, wait, what's this color showing?
[00:08:56]
One thing I would also avoid doing is adding, like, is it for text or is it for the background color, just because you might use it for text in one place and a background color somewhere else. So, as much as possible, generic, uh, you can definitely have layers of them as well, but to keep it simple, I would do something like this. Yes, Mark. Uh, there was a question in chat around, should we think about these as variables or constants?
[00:09:25]
Variables, yeah, so they're definitely variables. Uh, so here, um, well, first this sort of hints at it. They call them custom properties, but then to use it we use the var word. So, uh, we're coming in with a var with the open close. It's interesting because we're putting the name of the custom property within the opening and closing here, but then it's taking the value of that custom property to use over here.
[00:09:48]
So it's this weird thing where I'm creating a name and then using that name to find the value of that thing. It's how we use them. Uh, they're definitely variables because we can redefine them, uh, which is something I was going to look at a little bit later. Uh, and I think I still will, but there is the ability to have the global version of it, and then at a smaller scope, I might have a demo coming up actually at another scope that you go in, so it's inherited, but you can overwrite it at a local level, so within one component that's actually a different color or whatever it is.
[00:10:22]
So they're definitely more like a regular variable than a constant because they can change. Uh, I am also going to come in with a color for the other one, which would be my color. It's, this is always one I have trouble with. Uh, I was going to originally do color base. Because it's such a simple project, that made a bit of sense for me. It's my base color. I'm using it for a few things, but I decided for this course to stick with the naming system I usually use, which is calling my neutral colors just neutral, because they tend to stay, your whites to blacks tend to stay neutral.
[00:10:57]
And then I use a numbering system, so white would be 100, and then I can just have like a pure white 0, 0%, 100%. And darker colors get a bigger number, so the same way font weights work. Heavier fonts, bigger number, colors darker, a bigger number. That's the way my brain works with it. If you have a different system that you like, there's no harm in that at all. Uh, I am going to come in with 800 for this one, and the reason, first of all, I use 100 to 800 is because then it's easier to like slip extra things in between.
[00:11:28]
If ever there's, I have 10 values and then I need an 11th value, I can slide one in. If you know that's never going to happen, you can just call them 1234. This is just the naming system that I've got used to using. And the reason I'm doing 800 is because this HSL value goes to 20%, and I'm like, uh, maybe at one point they're going to want something darker in here, so I'm just leaving that door open to have a 900 that's closer to pure black.
[00:12:01]
So I can use those, this one. Var color neutral 800, the white I'm not going to worry about for now. We don't really need to have that one. I also spelled neutral wrong there. Uh, the color gold has to be my accent. We can come further down. This one also, you can also use a find and replace, if you'd prefer it'd be a little bit faster, but we'll do that as my color neutral 800. And the nice thing with having a naming system like this where it's like a numbered system, whether it's hundreds or single digits or however you're doing it, is just over time like every project you're doing, it's always the same even if the colors are actually different.
[00:12:41]
Uh, which just means again, you don't actually have to remember the values of anything or the names of things. It's just this consistent thing you're using from one project to the next. Oh, no, OK. Uh, so those are all set up now. The next thing I can look at doing are other recurring things that come up a lot, which is font sizes. So, font sizes, I use the exact same numbering system and I also preface them.
[00:13:07]
You can write in font-size if you want, just easier to put FS. So font-size, font-size, I use again like I would with a font-weight. Font-weight 400 is your normal. So for me, font-size 400 is my normal font-size, which in this case was the one I put on my body. The 400 is always whatever I put on my body. That's what I treat as my normal. It gives me room to have smaller ones, but you generally don't have too much smaller than whatever is on the body.
[00:13:34]
And then I can just come up in the scale with the different ones. I don't remember how many we have. But again, it makes it easy by numbering them to remember, oh, I just needed a little bit bigger. That component's using a 500 or this element is using 500, I'm going to use a 600 here. You're not, is it 1.2 or 2.7 or you don't have to remember those numbers anymore. Uh, I'm going to do up to 8. I don't know if we have that many though.
[00:14:21]
So this one was my var font-size 400. Those are all OK. So this is my biggest one. So 3 REM is the biggest. Uh, we should go the other way though. Let's find the next smallest one. This is the next smallest one, I think. So that would be my var font-size 500. And I bring that up right away. Then the next smallest one is the 1.5, so that could be the 600. And that was a 1.5. Refactoring is always fun, but it pays off in the long run.
[00:15:02]
Uh, the next one is this var font-size 700. We did have up to 800, perfect. And this, oops, I copied the wrong number though. I think that was a 2.25, and then this one is a 3 REM. And so when I do this var, the one I haven't changed is the one that was the M that I'd set up here. So if I come and take a look at those, I've still left this as an M because I still want to keep that relationship. I wouldn't make a variable that's an M unit if the purpose of that unit is to keep the relationship with the parent's font-size, just because it's kind of a one-off situation.
[00:15:33]
It's not something that I'm repeating or reusing in these different places, it's something that I'm only using in this one spot. So I just feel like in this case, having a font-size that's not a custom property is completely fine, uh, and I'm fine with doing it that way. Uh, line heights, I don't tend to do. I traditionally, I used to do font weights, but I haven't bothered anymore just because they sort of are already with their numbering system.
[00:15:57]
It's the numbers that are there, but you could make variables for like a font-weight bold, font-weight regular, so then you're not worrying about what number it is, you're just worried about using your variable for the font-weight. And yeah, that's all we really have in there. Almost everything is getting mapped to a custom property now, which is awesome. Uh, actually, one more that we could do is the font families.
[00:16:24]
So font-family, uh, this is where I do tend to use base or body for the one that's on my body. We had it as, we didn't, or no, we did, we had that as a sans serif. I said System UI is nicer, so let's switch that over to a System UI. And font-family for the headings. I have done heading in the past, but then invariably you end up having to put it somewhere where it's not a heading. This is one of the hardest names for me to come up with.
[00:16:50]
I'm up for suggestions if I have one in my mind, but I'm definitely up for suggestions because I like looking for better names. So for the font-family up here, assuming it will not only be used for headings, what could we call it? Accent, accent. Uh, I mean, if you're looking at display, display, yeah, like a display, yeah, for display fonts. So those are accent and display are two awesome names. Uh, you'll see both of them used a lot.
[00:17:14]
So display. I was originally planning to use accent, so thank you, Chris, for validating my idea. Uh, those tend to be the ones that I think you hear or see use the most. Uh, some people do just like saying serif, knowing that it's a serif font, it's going to stay a serif font, so it does depend a little bit, but I'm going to, since I had accent and because someone did say it, uh, I will say this is Overlock, and I don't think I made the font stack before, but I am going to say that it has a fallback of a serif just in case we run into problems with the font downloading for whatever reason.
[00:17:58]
System UI probably less important, but since we're doing the basics and building font stacks, we might as well say this has a fallback of sans serif as well. And then Overlock becomes var font-family of accent. And on the body, var font-family of base. And again body probably could work on that one because you're applying it to your body, uh, and nothing really has changed, so it was quite a bit of work to set that up and one of the most tedious parts in new projects because usually you don't refactor it this way, you could come in with a lot of these from the very beginning and just setting up your custom properties is part of the job.
[00:18:12]
It takes a little while to do it, but then we're going to see as we're going further in this project and doing more with it that having those in place really does help us out.
Learn Straight from the Experts Who Shape the Modern Web
- 250+In-depth Courses
- Industry Leading Experts
- 24Learning Paths
- Live Interactive Workshops