 They're my front end friends. The other day I recreated YouTube's tab animation for the underline when you go on the different tabs, the line sort of stretches and moves across. And I had a lot of fun doing that. But just after creating that, I saw a video on the CSS weekly YouTube channel where Zoran did a directionally aware effect for a navigation menu that I thought looked really cool. In this video, I will show you how to use it to create a direction of air hover effect. And that got me wondering if I'd be able to recreate that underline effect from the YouTube tabs, but with something that CSS only and directionally aware with hover and focus effects, instead of having JavaScript involved in it. And this is the final effect that I finally came up with. I think it looks pretty cool. I'm really happy with the finished result. So in this video, we're going to be diving in and taking a look at how I did this. And it's just a fun exploration of a lot of really fun things. And so let's dive in and take a look at how I did it. And this is what we're starting with, but just really fast before we get into it, just in case you're new here, my name is Kevin in here at my channel. I help you fall madly deeply in love with CSS and just web development in general. And if I can't get you to fall in love with it, I'm hoping to at least help you be a little bit less frustrated to buy it. So let's dive right in here where you can see I have this really simple navigation setup, the same type of thing you see on basically every site ever. And we're going to be playing around with this a little bit in my CSS. I haven't done very much. I just put a big font size on because it's a demo I'm using on the UL. I have a display of flex here just so they go next to one another. And then I have just a basic styling on my links and I'm being lazy and using opacity to change the color because I'm being lazy and I didn't want to have to pick colors. We want to look at how we can get that directionally aware CSS goodness to be happening on here. Now the very first thing that we're going to do is I'm using a gap here to create the spacing and that's sort of the normal approach I would take. But in this case, I'm actually going to replace that with a custom property called gap because I want it to be really obvious that this is the gap on my UL. So I'm going to go with the same name. Now I'm putting an underscore here. This is just to indicate that it's a locally scoped custom property and not something that would be coming from the root. So don't go look for it there. If you see the underscore, it's something locally scoped and doesn't live in the root. So with that gap, I'm actually going to use that on my allies. And I just realized like here, I didn't put nav like this is a really simple example. I'm not using classes or anything, but I guess we'll stick with it being a little bit more semantic in a sense. So we'll do a nav li just to make sure we're only in our navigation. But of course, you could replace these with classes or however you want to be working. So on these allies, what we're going to say is we're actually going to give these some padding. And I'm going to say the padding is my I want to do a calc first and then we're going to say var gap with the underscore just like that. And it gives me the spacing in between them again. The only problem is the spacing is twice as big as I want it to be because there's two rem of padding here and then two rem of padding back on that side. So that's why I put a calc there just to do a divide by two. And it goes back to how it started. So now it's one one rem on this one one rem on that one. But the reason I bothered doing this is it just makes it a little bit easier for the like how big our underlines should be once we get those underlines coming in by having this on the padding. So there's if you want to take a different approach for getting that spacing in there by all means, you could definitely do it. But for me, this was the easiest. Now what I actually want to do on these is we're going to do an av li after and on the after here, I don't know why we got a top, but there we go. We want our after. And because it is a pseudo element, we do need the content property on there. And let's give it a height of say three pixels, a position, the position of position absolute. And then let's give it a background color background, I'm going to go with orange red because it's a nice color on this dark background. And then let's also give it a width of 100%. But of course, I don't want these values to be for the entire, you know, right now, they'd be looking at the body, we get these huge lines that are showing up, which I don't want. So I'm going to go over to the individual ally here and to say position is relative, relative, spell things right. And then we get them all matching the size of their the parent. So the pseudo element is looking at the individual parents to figure out their size, which is awesome. But now obviously, we also want the left to be a zero. So they line up properly there. And we'll go in with a bottom of zero as well. So they're right there. I just realized this padding is on my top bottom left and right. And I'm using it as my gap. So we might want to just update this and say padding in line, just so you know, it's actually a working like the gap. And then the bottom here maybe could be a negative one ram just to pull it down that distance. Now, with this, it looks like it's one big solid line. But of course, if I came in on these widths, and I said 50% or something, each one of these allies actually has its own line coming across, but because they're all at 100%, they're sort of connecting to each other as they stretch along. And that for me is a good thing. And that's why I have this as the padding here, because if we'd had just throw a gap on here gap of one ram, let's say, then it would add that space in and I'd sort of have to play around a little bit with and you just be doing probably a calc to sort of pull, you know, you could do your width and then add it in and then with your left and rights, whatever, there's other ways of getting the same type of effect. I just found this one was a little bit easier to do. So they all sort of connect to one another. Now, before we worry about making it directionally aware, I want to get the hover effect when I just go on one of them that it's going to appear from the middle. And that's the easy one to do. So here on the after I'm actually going to come on and we'll come down here and we'll say scale is going to be a zero one and they vanish. So scale is its own property. You could do this also with the trend with, you know, the transform, and then we could have a scale here scale, and you can do it that way as well. And I'm going to be using different transitions and delays on them. So it just makes my life a million times easier. If I make that the scale and just to show you that they're there, we can do a point five. So we're shrinking at point five on the x axis, but zero on the y axis. So they keep their height, but we're shrinking them this way. And then what we could do is we'll keep it point five for now. And I'm going to copy this. And we can come in. And I want to say when I hover on mail I and I'm doing this on my live the link is in there. So it should be fine. So we can say hover and I guess you could do all of this on the link itself as well instead of on the list item. It wouldn't really change a whole lot. Let's just take our scale here and do a one. So now if I go on any of them, it goes back up to the original one. So we can bring that to zero. And then any time I hover, it's growing, but it's instantly growing. So we can also transition our scale. And for now I'm going to say 250 milliseconds can change that after, but at least we get this type of thing happening, which is the initial behavior that I want. And this will actually be the fallback as well. So if a browser doesn't support has, which we're going to have to be using, they're going to get this behavior anyway. So it still works and still looks pretty good. But we're we'll step things up for browsers that do support has, which at this point is, is pretty good actually the support on it. Now, what I'm actually going to do for the moment is I'm going to bring the scale back up and turn them all on. But I'm also going to come here and I'm going to say li nth child of three, just to select the pricing one, because it's going to be a lot easier to understand how this is working. If we just look at one of them sort of moving around in everything, and then afterward, we'll turn it back on for all of them. But just for visualization purposes, this is going to make a lot more sense. So we're just going on the li that's the third child. So one, two, three, that's my third li the pricing right there. So what I'm going to do is I want it to stay in the middle because we want that initial behavior, right? We want it to do this most if somebody just happens to hover on that and they weren't on one of the other siblings first, that's the behavior we want. So as a default, this is this is perfectly fine. We're going to leave it like that. If somebody was on about first, and they move on to pricing, I want the line to come sort of look like it's moving over from the about over to the pricing. So this is what we can do here. And this is kind of fun. We're going to say nav li hover plus li. And for now, let's just say color is going to be let's do hot pink is hot pink stands out. So now if I hover on any of them, you can see the next one over is changing over to pink. So it's if I hover on a list item that's in my navigation, the adjacent sibling, so the next li over will change color. So we can see it's working. Now, obviously, that's not what we want. What we want to do is select the after here. And actually, we'll look at a way we can sort of clean this up with custom properties a little bit in a second, but let's just do this really fast. And then we'll do that next thing of cleaning it up with the custom properties. And so what I'm going to do here is let's take this off, renew a translate. I'm going to say negative 100%. And so now if I hover on there, you can see it's moved over that way. And then we want it to be that, you know, as I go to pricing, it's going to slide over. So let's come up to here and we have the transition for scale. And what we can do now is we can also say that we're going to do a translate, and we'll do 250 milliseconds here as well. So we have both pretty years coming in and doing that to keep it all we have a scale and the translate there. So now when I'm here, that red line is going to be over there. And when I move over, it's going to jump to there. Interesting, right? So we slide over as we go that way. Now to really get this effect to work on my Li, we can also say that we have an overflow of hidden. And now it's completely vanished. And actually, that's because I did the bottom here. I just wanted to move it down. Well, we'll go with the bottom of zero on there. So it pulls it back in. And so we have the pricing there. And when I go to here, it's moving over that way. And then I can. So it's actually, you know, if we don't have that overflow hidden on there, it's moving over. But because of the hidden is on there, it's vanished. And when I come here, it slides in. Kind of neat, right? Now, this is nothing incredibly new. But what we can now do with CSS is we can actually choose preceding siblings. And this used to never actually be possible. But thanks to has it is. So let's come here and actually, yeah, we'll do it first. And then I'll clean up with custom properties. Like I said, I was going to do. So in this case, now what we're going to do is we're going to say and have Li as plus Li hover. And we don't need the Li there. Actually, we can just say plus hover. So if the sibling after it is hovering, we can do something to that one before. So let's just come here and say the color is hot pink once again. So we can see that if I go on something the one before it is changing, right? So that's kind of cool. That's and this is what enables this magic to happen. And so now what we can actually do is come in on the after on that one. And we can do a translate bit in the other direction. So let's say this is actually me positive 100. Let's go turn off that overflow for a second. I will comment that out. And so if I go here, it moves that way. And if I go there, it moves that way. And this is really where the magic is. And we do the overflow hidden. Now, and let's turn our scale back on to zero. So it's vanished. If I hover on top, the scale is coming in. But then if I'm here, right, we're, we're, we're moving over to the blog, we're going that way. And then it's going to slide in that way. And now if I'm on this one, and I go that way, it slides in from that direction. So we can slide in depending on which direction we're on. And so let's just take this off from being the end child, we can do this on all of them. Right? So if I come from the top or the bottom, it does that. And if I slide over, the whole thing sort of shoots over. Now, it's not perfect yet. I want to fix up this animation just a little bit, because right now it's a little bit clunky sort of how it's working, because we have it sliding and shrinking. And there's a few things happening at the same time that are making it look a little bit sort of like it's jumping to the next one, which is already kind of cool. It's not bad. But what we can do here, just to make like this section a little bit easier to look at where we're always having to select these afters, let's come here and we're actually, we're going to do a translate here. So let's say translate. And we're going to say that the translate is going to be bar translate. And I'm going to do a zero, zero is the default. So the translate as a default is zero. And then here, what I'm going to do is on this one, we're going to do a bar scale. And actually, you know what, we could even call this bar width, just and the reason we could call that width is even though we're doing it on the scale, the whole point of this is to control like the width of our elements. So let's let's call it width there. So now what I could do is I could actually come here and remove this. And I could remove all this. And I could just say that the width is now going to be a one. I just realized it's very broken. So we should give this a default. So the default will be a zero. So we have no width. And then when I have her on top of them, they will get that width of one that's coming here. Then over here, we could say is instead of having the after, we could just say that our translate, we have our translate can go to negative 100. Let's just copy this, paste it here, we can take the after off again. And we have the positive 100 in this direction. So we still get that same behavior that's happening. I just find this a little bit easier to be able to do it. And we're going to be making a few other changes on these as well. So not having to select the after every time, I just find it cleans up the code a little bit and makes it a little bit easier. So that's why I'm doing it like this. Now the other thing I'd like to change is actually on these animations and is to delay them a little bit too. So let's come in here first. And let's change this one to about 300. And we're going to change this one up to about 500. And then after that, I'm also going to come and add a delay to them. So here I'm going to do a var of scale delay. And I'm going to do this as a default of zero MS. And if you don't put the MS here, I do believe it breaks it because we can't use its animations and transitions are one of those places where zero does still need a unit. And let's do this one is translate delay. And if I was doing this, you know, as my own, I might do TD just an SD, just to make it a little shorter, but we'll keep it really explicit here. So if you go get the code after, you know, exactly what these are being used for. So there we have it, we have the transition delays and all of that. So for now, right away, you can see it's still working. And the big thing is when I go from here to here, I actually want it to start moving before the scale comes in. So I don't really want to delay. So for that, that would actually be on both of these, we could combine these into one. But what for now, let's just do a scale scale delay. And this will be let's say 300 milliseconds. And the reason I'm doing 300 is I'm using that number here, this could be another use case for a custom property as well, just so you have the same number coming for both of them. And let's take the same scale delay and put it on this one, it's going to start sliding over before the scale kicks in. So instead of doing the thing where as soon as you go off, it was like scaling and moving, I found it a little weird. Now it does still have this weird sort of little like clunkiness going to it, maybe you like the feeling of it. And now we'll do is we'll come in with a trans late delay. And I'm going to do about 200 milliseconds. And we can do that for both of these. So if I do that. Now, when I look there, and then I go here sale it like it stretches over and then it shrinks. Right, because we're delaying the we're delaying everything basically, we're just making sure that that translate doesn't start happening until there's a bit of like time and the other ones already come in. So it just gives us a bit more of that like gooey feeling that we're we're after and a little bit more like that YouTube one that we're doing. And I sort of want a little bit more distance here. And as we saw, if I move it with my bottom, the overflow hidden will hide it. So I think I'm actually just going to take this padding in line and make it padding everywhere, just so we have a bit more of a gap. And I think that looks a little bit nicer. So that's looking pretty good. I'm really happy with that. And the reason again, if I was just doing like my width, and maybe if I was only doing my translate and the translate here, I probably wouldn't bother with the custom properties and breaking it all down. But because I find it a lot easier to say like, I'm just doing my scale delay and my translate delay and breaking these pieces up a little bit like this, I find it a lot easier to do it with the custom properties. And then you don't have to bother with the hovers. Like I said, the afters, I should say now as far as supporting this across different browsers, all of the fancy stuff is basically happening in this area right here. So and it's really the has that we don't want, right? This is what we have to check for support for. So I'm going to do an at supports. And then we can do selector. And then I'm going to say has and we can just put anything here, right? If has h1, if the browser is able to do this, then what that means is we're going to do all this fancy stuff right here. So we'll paste that in. Now I'm in Chrome right now. So it should continue to work. And we can see it is working because has h1 is supported by Chrome currently in Firefox though has is behind a flag. So if I come and check this out in here, you can see it's going back to the old way of working where it was always growing from the center. The reason I want to bother with that is just because if I didn't do that, the has supports thing here. And we look at it in Firefox, this way is going to work. But if I go over in one direction, it will sort of work, we're getting like the weird movements coming from different ways. And it's not consistent with how it's working. And it just feels kind of awkward because it only works in one direction, but not the other direction. So just by wrapping anything that makes the direction related stuff in this at supports means that if it's supported, it's supported. If it's not supported, then it's not supported. There is another downside to this in general, which is if I go here and I go really fast, we sort of get this type of thing happening. This is a CSS only solution. This is the type of thing that can happen. It's never going to be a perfect solution. And I did mention focus as well. So this actually doesn't work super well, when we're focusing. So what we could do is we could just come here and give this a fallback as well. I do have obviously, if I do it now, we have like the default, but we can say here is nav li and we can't focus on the allies, but we can't we are focusing on something inside those allies, we can do a focus within. And so now if I tap across, we get that default behavior where it grows from the middle. It sort of works if you do it on the inner parts here, but it wasn't working exactly the same. So for me, this is sort of like the safer bet for focus states. And then we can keep this here. Again, when I push this production, maybe not just because of this type of behavior that could happen, but I still think it's a really fun effect. And I really hope that you learned a lot of really fun things along the way with this as well. Now I definitely would recommend you check out the CSS weekly channel. So I have linked that down in the description. And if you'd like to learn more of the really cool things you can do with has including this sort of gallery effect where you're affecting every item except the one you're hovering on, then you can check out this video right here. And with that, I would like to thank my neighbors of awesome TT LLD Andrew James and Rico, Michael, Simon, Tim and Johnny, as well as all my other patrons for their monthly support. And of course, until next time, don't forget to make your corner the internet just a little bit more awesome.