 Hi there my friend and friends writing JavaScript to do things that are like styling related has always felt a little bit strange to me there's stuff JavaScript should do but whenever it just comes to styling only then it seems like CSS should be enough to do the job and luckily as CSS is maturing as a language and we're getting a lot of new features there's new stuff that is opening up like creating a button like this one that's directionally aware at least a little bit directionally aware that we can do with basically CSS only there's a few little tricks in getting it done and while we are going to have to leverage a newer CSS feature that actually has better browser support than you probably think it does it also doesn't ruin the experience for people who have an older browser so if you're curious about how we can build that then let's dive right into vs code here and I'm assuming the first thing you're going to want to do this is a button I'm not even going to throw a class on here obviously you'll probably have a class maybe it's on a link that looks like a button whatever let's just do click me hit save and when we do that we have a big giant button that is right there and that's because I've already added some styles here just to speed things up there's really nothing fancy that's in here I've just put some padding a background color made the border radius so it's curved and you know you could do this with any button that you want basically so whatever styles you want I have a hover and focus visible changing the background on there put whatever starting point you want for your button and it should work there is a little gotcha here though and how this is going to work which is we're going to add some more stuff here and so I am going to come in here and I never like doing this but we're going to add a span there we're going to add a span here when I first thought of doing this I was going to use pseudo elements but we can't detect hover on pseudo elements specifically so I wasn't able to work now we'll admit this is a little bit annoying having to nest those in there especially if you're just writing like vanilla HTML and CSS if you're using something where you're creating a component it really wouldn't be the end of the world so it depends on how you're setting things up but if this is a react component or even you know spelt that or whatever it is that you're building out then you'll be fine you just call it fancy button or something and you never have to worry about those spans again but we're going to leave it like that for now because we're keeping things nice and simple so people can implement this however they want and so yeah we have those two spans there and so we're going to have to set those up so let's select those I'm just going to do button span so I can select both of them and most of these styles will apply to both but we'll sort of break things down from there but the first thing we can do let's give them a background we're not going to see them at the beginning but we'll do background we'll do orange red because orange reds kind of a nice color of course they should have a position of absolute on them I'm going to give them we have the position absolute and actually this is one of those things I didn't put on the main button yet I'm going to add a position relative here we're going to have a few things we will be adding to this button that are specific for this effect to work but we have the relative that's going to be here and then the absolute on the span and let's give them a width of 33.333 percent I don't know how many decimals you really need in CSS but that should do the trick for this now we will not be leaving the width like this but we're going to set it like that for now we could set the height to 100% too just so we actually see them and now we actually want to position them in the right places so for that one I'm just going to do button and then do first child now this effect you could actually add a lot more fidelity to if you had a lot more pieces in here but for a button effect like this I think just having three zones is going to be enough we're going to have a left zone a right zone with the spans and then the middle zone will just be no span at all if you are going to do it with more you'll want to use nth child and like select based on number but we're just going to do first child for this first one and so we can just say a left of zero and a top of zero so it gets positioned right there and then we can duplicate this one right here but choose this one as my last child instead and instead of the left we can do that on the right side and that's basically all we need to do to get those in the right spot we'll come back to the span right here and we well do we well we will do a z index and negative one to move it backward but I don't actually want them to be lost completely do we doesn't matter doesn't yeah I think we hmm I'm not sure we will need this for something else though so I'm going to do my isolation of isolate which creates a new stacking context and keeps them from going behind the background of my original button you might be saying Kevin that's a little bit weird because we don't want to see them we are going to change the color of these I'm going to drop the opacity for now just so they're not so bad but we will eventually be making them completely transparent anyway so you're not going to see them the other thing this makes us realize is right now they're sticking out the sides we will have to turn an overflow of hidden onto the button itself but I'm going to do that a little bit later just because having the overflow on there is going to help everything make sense on how it's working and then we'll sort of do the last steps at the end to turn off all of those things so now is the real trick and I actually shared this on the community post earlier and everyone assumed I use pseudo elements I guess because they know me but we're only going to use one of them and it's going to be for what creates that effect right there so we're going to say on the before let's give it a width the width on this actually it's a before before we do the width we'll give it content so it exists we will give it a position absolute because we need to be able to move it around and it has to be it like whatever it needs to be absolute so it's out of the flow I'm going to give this one a background of hot pink so once we start giving it size we'll actually be able to see it and I'm going to give this a width of 10 percent I obviously went with like a gigantic font size on here but hopefully by this being a percentage it just means that it would work no matter what size you end up setting things to the only thing that's really important with the width here is that it's smaller than the entire button because it's going to make it a lot easier to center and the reason for that first let's give this an aspect ratio of one which just means the height and width are the same and let's give that a border radius of 50 so it is a circle and I want it to be dead centered inside my button so to be able to do that the easiest thing to do is an inset of zero which means top of bottom left and right of zero and a margin of auto and it's going to go right in the middle if we had our circle being bigger and then we were trying to do different things to shrink it down that sort of doesn't work but this is just if you're using position absolute or fixed inset zero margin auto it's centered you don't need that weird translate hack to actually get things to go always super handy to be able to do that now just like those other you know these transparent things that will become in our spans on the edges I should be saying just like those we do want them to be behind I don't want this to actually cover the text so on here I will also give this is that index that index of negative one just so it's behind the text itself it's more of a background effect not something that's going to be at the forefront and now is actually where the magic happens we have everything set up to create what we need to happen here so what we're going to do is let's do it just so it works out of the middle and then we'll get it working for the two sides and so to do that it's actually the easiest one we're just going to say button active and we can choose the before and so when and active means like we're actually clicking on it so this would work on a phone too it's not just a hover effect right so the active before means when the button is active the before will do something and so when the button is active the before is going to get a scale and we're just going to scale it up so we'll do that as a transform we could do scale as its own property now as well but we'll scale this up and the important thing is that it ends up being big enough because like a lot of the time we do a scale two or something but it's only twice as big so you just want to make sure this is a big enough number and I'm actually going to make it a really big number which might seem a little bit like overkill maybe we could actually shrink that one down a little bit and we'll see but maybe we do need the 20 and it's because we need this to actually get really big if we're gonna have it work by coming off the two sides as well because right now in the middle obviously it's covering the entire thing but if the circle is growing from here we need it to reach all the way over to that side but before we worry about that let's just come here and do a transition of the before we'll do scale for now so the scale um or not scale transform I should say transform and let's just say 500 milliseconds so we actually have something so when we click it grows we let go it shrinks nice and simple right um let's change this color now and I already have this color right here again use a color that works for you it's just a dark blue color that I'm using and for now actually let's come and change these spans to be transparent um and I guess if we didn't even declare anything on there it would be fine but it's just kind of ugly so now we'll turn them back on um if we need them but when I click it gets really big when I let go it gets really small so that's sort of the effect that we're after but obviously we don't want it to explode outside of the button like that so as I mentioned up here we can also come with an overflow of hidden on there and so now when it grows it takes up all the space and then when it goes back down so it already looks kind of cool obviously there's a few other issues we don't want to see it while it's in the middle and everything else but I'm going to leave it there for now um and you know what let's let's just do our background of hot pink for now just because it makes it easier to see what's happening because now we want it to go from the two sides and that's where the I said the magic was happening before this is where the real magic happens uh by using has so we can say has and then I can choose first child active and this is kind of interesting that it works uh in a sense because even though I'm clicking like here it's the button that's active less so the first child which is that span but hey it works and just to show you it works the background here will turn to red and so if I click here it's the same if I click on this side um let's turn off the scale change for a sec it click here everything looks normal if I click on this side it changes over to red so what that means is we don't actually want to change the button itself what we want to change is the before on that button that has the first child which is active um and if you remember I use margin auto to center it so like there's different ways we can move stuff around my favorite thing to do is to say if it's the first child the margin right uh left I should say the yeah the margin left will be zero and that just means if I click on this side it's moving from there over to here that's all that's going on we'll turn turn off that scale again to really see I click here it moves to that side is the margin auto which was centering it is now zero so it moves over to that side now we can take that same thing do the margin right if it's the last child and again this is where if you had more fidelity you'd have a lot more work to do with like different positioning stuff on this but now if I do that click in the middle it stays in the middle I click on that side and if I click on that side it moves over to the right side because it has a margin left of auto which pushes things all the way over nice and simple the simpler we can make things the better and then when we scale it up like like in the middle it grows from there it grows from that side where it grows from that side pretty cool now it's not perfect but most of everything you need is here the finishing touches here are just to make sure that when we let go see how it like jumps back to the middle and it always shrinks to there we can't really prevent that with this type of system so what we can do instead of trying to prevent that or maybe you could actually with like transitioning your margin left and having delays on stuff so if you want to try that I don't even know if margin would work to animate it to be honest so anyway we have better ways of fixing this up anyway so the first thing I'm going to do is on this before here we can set the opacity and my css here is not very well organized but we can set an opacity of zero on the before so now we can't actually see it and then I went to click expecting it to show up for some reason so when we have the button active we can make the opacity go up to one and so if I click in the middle it appears and then disappears still not perfect by any means but it's going to be better now the cool thing with that is it also works on the sides where the opacity will come up because the button is active even if it's the child that's inside of it that we're clicking on I think what we're going to do now we'll bump this back up to 20 there's a few things here where if we click this way the speed of the animation is actually pretty good when we go on the sides if we go in the middle it's double the speed because of the way it looks I guess right where it just grows super fast from the middle because of we're getting sort of the side whatever it looks way too fast from the middle whereas from the sides it looks a little bit better and so what I'm going to do is I'm actually going to take the transition off of there and I'm going to move the transition here and there's an important reason I'm going to do that so I'm going to have the transition here and then what we're going to do is we're going to select this and we get I mean it's just one line of CSS but I want both of these here and we're going to have the transition on those as well that would be this one and what we can do now is I can actually make this one longer so I can say this is like a thousand milliseconds so going that way it takes a thousand milliseconds I go on the sides here it's doing it in half the time and it actually makes it feel a little bit more just like organic in how it's working so we have it growing in that way we have it growing in that way and then we have it coming in that way the other thing we could do here is add the opacity in here as well so we can just comma opacity and do that at like 250 just so it like it's we're sort of fading in the opacity a little bit and actually we need the opacity on this one too opacity and for that again we could do it at like double the speed you could set this all up with custom properties you could have one thing that's controlling it and you update one number and sort of all of these get adjusted based on that number so now if I click in the middle it grows in the middle if I click on the left it goes that way if I click on the right it goes that way it's looking good but obviously when we let go it's kind of weird that it just vanishes it doesn't look fantastic yet so I'm going to take this transition here and I'm going to bring it on to the button before the entire thing and I'm going to drop it here now we're not going to keep everything the same but I'm going to show you what we're going to do and we're going to start with a really slow opacity change just to make it really obvious how this is working so if I do here it looks okay but when I let go it's weird right that it circles back onto the center so for me the easy fix here is actually delaying the transform animation from happening by the length of the opacity one so for now we'll put a thousand milliseconds so what now what happens is if I transition or when we transition it's just going to fade out and then so if I do this side and then it just fades out if I do that side it just fades out because the transform hasn't come in yet the transform is still exactly where it was at the end so it's not actually scaling down it's staying big and it's dropping the opacity the thing with this is over a thousand milliseconds it still doesn't look good but if we do it very quickly over say 200 milliseconds the problem that's happening now is if I click and it grows and I let go it's still delayed so like if I click on this side it's fine if I let go and then click again it's coming in because that delay we're still it's still counting down that 1000 milliseconds so this is really important that this number and this number do match each other and again maybe a custom property there if you wanted to sort of improve on things a little bit could work so now if I go here it fades that way we can go here we can go there and when we let go it's always fading out the one problem is the color of it being hot pink I don't think looks very good either so now we get it from the middle and of course you can update the timing on all of these if you make it faster make it slower whatever you want lower the opacity of this we can come in at like a 0.25 or something like that this is the space separated syntax where you do use a forward slash so it's a little bit more of a subtle effect rather than that in your face one it really depends what you want to do and you know you can play around with it have some fun with it and use it however you'd like and I did promise to talk a bit about browser support and basically this is using has to function properly but if we didn't have has working in let's just come and put this back up so we can see it a little bit more clearly it's going to go from the middle or grow from the middle or grow from the middle so if you're on a browser that's not currently supporting has then you'd get a little bit of a different experience but it's still going to look cool it just won't be as sort of cool that it's coming off the sides or whatever and you might be saying but Kevin has doesn't have great browser support but guess what that's not bad we're only waiting on firefox really at this point and obviously for some older browsers that it will never be supported in namely in safari on old iPhones and stuff but it's already past 86 percent so using it for progressive enhancement like this I think is a pretty good use case of using something like this where you're not actually ruining the experience of anyone and if this is your first experience in seeing has and you'd like to know more about it and some of the stuff it can do and a bit more to understand how it's really working I have a video right here where I break it all down and look at a few cool examples and with that I would like to thank my enablers of awesome Enrico 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 part of the internet just a little bit more awesome