Lesson Description
The "Decorate Cards with Pseudo Elements" Lesson is part of the full, CSS Fundamentals course featured in this preview video. Here's what you'd learn in this lesson:
Kevin demonstrates using pseudo-elements to add visual labels to cards, like tags or badges, while discussing accessibility concerns and practical limitations.
Transcript from the "Decorate Cards with Pseudo Elements" Lesson
[00:00:00]
>> Kevin Powell: So now that we know about pseudoelements, I think we can add a couple to our project. We're going to add in a little on sale tag to some of the elements, and we're going to add in this little featured course type thing on other ones. If you haven't been following along but you do, starting code is available as usual in the same ways we've been doing so far. Let's turn off the grid inspector because we're not going to need it in this case.
[00:00:27]
And for this one, we're probably going to need a bit more padding actually because our text is going to start getting in the way of things. We do need a decision to make here, and there's something we haven't looked at yet, which is an attribute selector. I might have mentioned that they exist earlier on, but let's go full screen for now in our CSS. Or on the HTML I should say. Like we don't need this dark BG anymore.
[00:00:50]
I'm going to take that off. Dark BG be gone, save the file. So yeah, we have to decide like how would these courses be indicated that they're on sale or that they're a featured course. So let's say the second one is going to be on sale. Our fork pin skewer course is now on sale. You could do this in a number of ways. This could just be done with a sale class being added to it. It's not very hard to do, even if you're doing it with JavaScript, you're inserting it, you can toggle classes on and off, so it's an option.
[00:01:26]
Another way that it can be done, it's very easy to manipulate JavaScript with JavaScript. It's very easy to manipulate HTML things when you have a data attribute. So it could be something like data sale is going to be equal to true. And that could be something that you do or data state sale, things like that we could have coming on. I'm going to do it this way, just instead of using a class, just so we can learn a new way to style things and select things that we haven't looked at yet, but there's no harm in having this done with a regular class if you don't like the idea of using a data attribute.
[00:02:05]
But if things are being updated with JavaScript, instead of having to do it through the data state and then also or a data attribute and also a class, you might as well just hook into the existing data attribute that the JavaScript is handling. Keep doing that. I apologize. So to be able to do that now, let's go over to the CSS. We'll save this. And I have a course. So let's come all the way down here.
[00:02:34]
I'll come after we've selected all of them. And I want a course. Only if it has an attribute of data sale equals true. So a data selector, or yeah, an attribute selector I should say, is our open and closing square brackets. I'm not putting a space here that would work as an attribute selector, but then it would be a descendant, so I'm doing that as the compound selector, and I can say here the full string, data sale is equal to true.
[00:03:10]
And that will select it in the same way. So classes are more convenient. They're just a way like a hook to get the attribute of class. Technically speaking, you could do an attribute selector of class is equal to of course. That would also work. I wouldn't do it, you know, it's a lot easier when you can use a dot as a shortcut or a period as a shortcut. But other times you might want to select something by the attribute, so this is one way that, or this is how one way you can, it is the way that you would do it.
[00:03:46]
Now in this case, I don't actually need to select this element, and well, I'm selecting it, but I don't want to style it differently. I want to add content to it. I want to add a little stale sale icon. This is where we do want to talk about internationalization. We're adding content through an after, or I'll do it with a before. So you do potentially want to be a bit careful with that, but it won't get translated and we're adding some content in, so just do be careful with that, but I think it's still worth examining how we can do it.
[00:04:24]
We're in here, we can do a string of sale. And let's go take a look at what that's done. I have the word sale showing up right here. So it's inserted it as the content before all the other content within this course. Let's just make it so we can see it a bit better. Background is red, just for now while we're doing the demo, so this big bright thing shows up, we'll have a red background on it anyway when we're done, so that works.
[00:04:51]
It does raise a question though, if we talked before about the order of content, so do you want that to be the first thing or not? Should it say sale and then say the name of the course, or should it say the name of the course, then sale? Because it's pseudo content, maybe you could argue this is fine. Just to talk a little bit more about the idea of containing blocks and other things, I'm going to do this course, data sale equals true and the course title will get the pseudo element instead, and maybe we say it's an after.
[00:05:27]
So we're saying the name of the course, then we're announcing that it's on sale. This is where we're getting into more complex selectors. Mentioned before, we want to keep selectors simple. So when you start getting into these very specific situations, maybe there's times where this type of thing can pay off. I'm not worried about specificity, other issues, order getting in the way here because I'm dealing with such a specific use case.
[00:05:49]
I don't see how anything else is going to start conflicting with these. I might not, I'm not going to overwrite other styles that are coming from somewhere else, so I'm not too concerned about it. So now my sale is over here. And that's kind of weird because if I want to position it all the way out here. You might think that's going to cause a problem. But let's go and do it anyway. Position absolute.
[00:06:24]
And then we can say left of 0. Top can be a bit magic number. I'm going to say top of .75 pixels to guess, probably way too big. Not terrible, actually. And I've moved it on out. Did I position? Absolutely, yeah, it's working. So it's moved on over to here. Now, in a way you might be going, how come the absolute is positioned to the card and not to its parent? Anytime we use a position of absolute, we're positioning it to its containing block.
[00:06:55]
Containing blocks are not the direct parent of it. They're the first ancestor that has a position on it, and the first ancestor that has a position on it isn't the course title itself. We never declared a position there. So it's going all the way back out to the course itself, which has the position of relative on it. So we've pulled it out two layers and it's getting positioned to there. It's one of the reasons why knowing what a containing block is, is super important, because you're not always going to have that direct relationship of the parent to the child, and you're just positioning it.
[00:07:25]
You might have something 3 levels deep, but for whatever reason, you need that positioned to that ancestor that's all the way out there, a little bit like what we're doing now. Really, really useful when you understand how that works. Now we can style this up a little bit nicer. I think I'll shove it up a little bit. Maybe it's a 60, 65. This is, at one point, positioning it does become a little bit magic number.
[00:07:53]
We can give that the same padding that we had on this one, I guess, so the padding. I don't remember what it was. It's probably 10 pixels. I think we did a 5 on the top and bottom. 10 on the left and the right. We could come in with a nicer color. I think I did have a nicer one. We could save it as a custom property, so maybe that's worth doing just so we can talk more about that as well. Let's go all the way back up.
[00:08:18]
We had our accent, we have our neutrals, now we have a red color that doesn't belong anywhere. Color something 400. We'll come up with a name. Let's get the color. Start with the easy ones, the ones that you know. HSL 0 is red. I'm going to do like a 20% to get a bit off red, 75%. 75%, I don't know, we'll try, see what it looks like. I could just color pick the design, that would be the smart thing to do, but we're learning new things.
[00:08:51]
I did not come up with a good color, apparently that is yellow. Oh, I'm too bright. I meant to do that at like a 25%. We're going to use the color picker here, because I'm not getting a good color. We'll go more something like that looks pretty good. And just for consistency, it doesn't actually win anything or change anything, but just so all my colors are the same, I do like cleaning this up, so all of them look the same right there.
[00:09:24]
What would you guys call this? Any suggestions? I might go real specific and put sale sale. Definitely it could work. If this is the only place the colors coming up, it's not the end of the world, it's not accent because we have an accent. It's something that definitely is going to stand out. Naming is hard, if you're working with a designer, hopefully they're naming their colors and then you don't have to worry about it.
[00:09:47]
We can definitely go with color sale. It could be, you often will have like states if you're using any systems that exist out there. Red is often a data error, yellow's a warning, blue's an info, green is a success. So those are common ones, but in this case saying the sale is an error can feel a little bit weird. So naming things is hard. The more colors you have, the more problems you run into naming them.
[00:10:32]
We can stick with sale. I don't mind unless somebody has another suggestion. We'll go with that. So let's come back down all the way. And where we had the red. We can fix that up, which was our var. Whoops. Color sale. 400. Probably could be a little bit brighter. Try 45. This is why I like HSL. It becomes very easy to adjust the colors when I see that, oh, it's darker than I thought it would be. So I just come in with a quick adjustment there to get the new one that I want.
[00:10:55]
So let's go take a look. It looks like I wanted the other font family in there as well, so we could switch out the font family, and then that one won't be terrible. We potentially have run into a problem. I'm just going to look it up fast, so I don't scroll around everywhere. We have potentially run into a problem because we're using a position absolute that we're going to overlap some content in certain situations.
[00:11:22]
So let's try our font family first, which was our var font family accent. And I'm going to go full screen here just so it's taking up more room. We also need some space underneath that. I'll talk about that in a minute. But anytime we're using position absolute like this one, it actually looks like it's fine because it's slotted into this spot. But this title is only one line long. These titles are two lines long, so if one of those was a sale, let's go and make one of those a sale at the same time.
[00:11:57]
Just so we have it on more than one of them. Data sale is equal to true. We'll make that bigger again, and now we've run into this issue. So it's very important when you are using position absolute on anything, but you're checking for these potential issues from coming up. There's nothing that can really prevent this. Position absolute is out of flow, there's no detection, there's no way of saying like, except in this situation, make the thing taller to accommodate, you just have to make sure that you're setting things up in a way, and especially as you start moving things down or positioning things, you just want to ensure that the area that you're using isn't an area that can actually end up getting overlapped on.
[00:12:35]
Because it's very common that we start seeing these things pop up when you start throwing position absolutes everywhere. In this case, we know how far down we've come, so you could even do like a calculation on this if you wanted to say like the padding size, and then this is always going to have 10 pixels there, if you wanted to. So my top is currently 65 plus it has some height on there, and the course top padding is 85 pixels.
[00:13:05]
So again, you could think, OK, 85, I'm moving down by 65, so that's why there's the potential for overlap because there's not enough space there. And you could try and just come up with a number that's always accommodating for that, or just go big enough that you know you won't run into an issue. You don't have to do any math on this, but just be careful with how you're setting things up and ensure that the space is available for it.
[00:13:28]
And I think if we did something like that, we'll be completely fine. If you end up with 3 lines in your title, maybe you have a problem again. So just do double check, make sure you don't start running into weird things as soon as you start using position absolute, it does open up those doors. Now we also wanted the little feature tag on some of them, so let's come over and we could add another data attribute.
[00:13:53]
Let's go down to this one, when to trade pieces. And so here we could say this is a data featured, and we could just even do data featured, it doesn't have to necessarily have a true or false or anything like that. I do want to be able to have a featured and a sale, so that's why I'm not doing like a data state is featured. Because if it was a data state and then it's featured or sale, you can't with data attributes, you can't have both at the same time.
[00:14:31]
So I'm treating them as individual ones, but again, you could be doing this with classes as well, it wouldn't cause any issues. But we'll just data featured is equal to true. There's a lot of different ways to handle this type of thing. So we take the same type of approach over here. Course, data sale is equal to true. Then where are we putting this? Where do we want to say it's a featured? We could take the exact same approach if we wanted to, with one caveat.
[00:15:02]
If we wanted to be able to have, actually, let's do it this way, and then we'll fix it after. We'll say course title after is going to be a content. And our content this time. Good thing I remembered about the Windows period, because I'm just going to throw an emoji in here. Star. And get the star. I apologize if you're on a Mac, I don't know the shortcut. You want data featured, not sale. Thank you.
[00:15:32]
That are featured. I think on the Mac, if you just hit the function key, it'll pop up the menu and if that doesn't work on your Mac, you can under the edit menu, pull up the emoji picker. Perfect. Thank you for that, Dustin. So I can bring that content in, and we can see that's showing up over here, we now have a star emoji coming in. You could also do this with an SVG, an icon, an image, you could, we saw before, I didn't include the example, but if you have an actual file, you just bring in your, you know, my star.svg or whatever it is from your images folder, that would also work.
[00:16:28]
If it's a URL though, it does not go in quotation marks, you just do a URL like that. But we're just doing it very simple. We can bring in a star emoji. Once again, position absolute. Top of 0, right, maybe 20 pixels, so it's not quite touching the edge. Background var color neutral 900. Maybe a small amount of padding on there. We got our little feature tag coming up, looks OK. One problem with it is that a star emoji is not the most accessible thing in the world.
[00:16:57]
We'd also, I mean this isn't even the best thing from a sighted user point of view, because who really knows what the star icon is to say that it's a featured one, but we can come over here, do a forward slash, and then say this is a featured course to provide alt text for that content property. If ever it's just purely decorational and you don't want to have any alt text for it, just like on an image, you can leave this as just a blank string, so it's completely ignored, because emojis will get read out.
[00:17:28]
I don't know how screenwriters do it, but like they have their character thing that so like it might say star emoji, different ones might say different things, so in this case, you're probably better off saying it's just decorative or saying it's featured a featured course, and once again this will not get translated if your site was being translated, so just do be aware of that. So all of that's working, it's there, it looks fantastic, but I sort of hinted at this could potentially cause a problem.
[00:18:07]
Because if we have a course that is data featured and data sale is also equal to true. It's only showing me one of the two of them. And it's only showing me one of the two of them because we're both, we're using the same pseudo element for both of these. So this is something I very rarely happen, but I just wanted to talk about it where we have the same specificity selector selecting the exact same thing even though it's generated content that we're generating.
[00:18:36]
We're all the same properties coming around here, so it's using the second one because order wins and it grabs that one and our sale never exists. So it just means that if you are going to potentially have multiple things coming in through generated content like this, the pseudoelements do need to be placed on different elements. We have before and after. I really wish we could do like an after after.
[00:19:01]
That would make me so happy, but for the time being, we cannot do that. For the time being, we're stuck with only two pseudoelements. So instead of this being on the course title, I could always move it to something else, the course description. So it could read the description, then it could say that maybe it's the course description before. It's the positioning of it won't change because the containing block hasn't changed.
[00:19:28]
So as long as it's on the course itself or any of the descendants of the course, it will get positioned correctly. The one thing that we do want to be careful with is in this case, we could even do something like this where we're saying featured course colon. So maybe course title before makes sense. Because you think about it, if it's being read, it's going to say featured course, when to trade pieces.
[00:19:53]
That would make sense to me, so maybe that's the approach I would take here. But yeah, the main thing that I wanted to mention is just if we wanted to have both, except I still don't see both coming up, so we do have to double check that, because I thought I put two of them on here. But I might have made a typo. I put date sale. Data sale equals true. Ah, there we go. But just to show you that I wasn't lying before, if they were both on the after, actually we've broken things even more because we now have conflicting things that aren't working, but this has a left and a top, and this one has a top and a right, so it has a left and a right, we have weird stuff going on and it breaks everything.
[00:20:32]
So we just want to make sure that this is on different pieces of our content with the generated content that we're bringing in right there. Before we move on from pseudo elements, I do want to say, I mentioned earlier, there's a lot of them. Before and after the ones that you'll almost most certainly be using the most. You'll be seeing a lot more come up in the future. A lot of new CSS features that are being added are using new pseudoelements.
[00:20:59]
View transitions have a whole bunch of them. The new select menus have a whole bunch of them. I'm trying to think of a few others, but I know there's lots of pseudo elements that are on the way now. I've put a list here for all of them. If we scroll down a little bit, we'll get the full list. There's selection targets, highlighting before, after, columns, markers, backdrop. Column does not work with grid, by the way.
[00:21:23]
It's selecting it only if you're using multi-column layouts, which are a little bit more niche. Scroll markers, there's other stuff and it goes on and on and on. A lot of them are for very specific use cases. So you'll come into situations where you're learning about a new feature and you'll just see that feature happens to come with a couple of things. One of the ones that I did mention here at the bottom is to play with marker and selection.
[00:21:59]
Marker lets you change the bullet points on lists, you can just set a color, you can also change the icon to other things by changing the content. The only problem with it is, it's been around for a bit now and Safari still hasn't decided to support it, but it's still kind of cool. And selection, we'll look at selection really fast because it's so easy. We can just come all the way up. Let's just do it here.
[00:22:22]
Selection background var color accent 400s, we're using one of our brand colors, and now if I select text, it will use my color as the selected color. It's not really a big like wow moment, but it's one of those things you can just sort of increase the look of your websites a little bit, but you'll notice it can cause problems, so be very careful using it because my selected text is now unreadable.
[00:22:48]
You could come in with lower opacity is one way to do it. The default, if you don't have a selection on there. Well, actually, I think it always changes the color of both of them actually, so I would probably say you want to do the same thing. You can also say the color here is always going to be color neutral 900. And that way you're being safe, your text will always be black and you can actually read it.
[00:23:01]
So there's limited things you can style on a lot of pseudoelements. Marker is one of them. I believe we can't do things like padding on this, we can try. Yeah, you can't add padding to the selections, it would just make things look really weird. So color, background, I'm not even sure what else is possible, but if ever you're looking for things to do, diving into the list of pseudoelements can be a fun way just to explore and see what's possible.
Learn Straight from the Experts Who Shape the Modern Web
- 250+In-depth Courses
- Industry Leading Experts
- 24Learning Paths
- Live Interactive Workshops