Building the Active Server Indicator using Group and Transform Utilities

Sam Selikoff
InstructorSam Selikoff
Share this video with your friends

Social Share Links

Send Tweet
Published 3 years ago
Updated 2 years ago

Let's build the active server indicator (the final piece of our server buttons) using an absolutely positioned div alongside Tailwind's position utilities. We'll then learn how to use Groups to affect the styling of the indicator when hovering over the ancestor link. Finally, we'll use the scale and translate utilities to add the final bit of polish and match Discord's UI.

The code for this lesson is divided into two sections, with this you can see the progress on the code.

  1. Begin
  2. End

Instructor: [0:00] Let's finish up our Discord button here by building the active indicator. We'll start when our button is inactive. To build this, we'll use an absolutely position div right here.

[0:11] Let's come back to our clone and start just by turning this anchor tag into a div, wrapping it with an A, and we'll make this anchor tag relative, and we'll add a new absolute div right here. This will be our bar. In Discord, it's this white bar over here.

[0:32] Let's just start by making it background white, and we'll give it a width of two and a high of two. There we can see the beginning of our status indicator. Now we need to move this over.

[0:46] We can position absolute elements using utilities like top one to move it down from the top, top two to move it further, or even left one and left two.

[0:59] This offsets the element from the left side, but we can actually stick a negative sign right in front of this to invert this value. Left one moves it over by one unit on the spacing scale, left two, two units, and so on.

[1:14] The cool thing about Tailwind spacing scale is that all these spacing utilities use the same value. We can see right here that we're using a padding of three units to account for this space right here.

[1:26] If we make this negative left three, our bar lines up perfectly with the left side of the screen. We want the status bar here to center in our button, just like it does in Discord. My favorite way to center anything in CSS is with flexbox.

[1:45] Let's go ahead and make a flex parent, and we'll pull the absolute class and the negative left three class up here. Then let's come over here and inspect our new container. For this to work, this will need to actually fill the whole height of our link button right here.

[2:06] If we hover over our link, we'll see it's not really taking up space in the Dom the way we expect. That's because we're using an A tag, which is in line. If we make this block, now we'll see when we hover this, this is actually taking up this full space.

[2:26] With any luck, if we make this height of 100 percent, we can see now that this is a full height. Let's come over to our flex container, make it height full. Now we should just be able to use item's center to center that bar. It works. Now let's work on the size of the bar.

[2:49] Over in Discord, we see it's a little bit narrower, so width two, let's bring this down to width one. That looks pretty good. Then for the height, well, it's a little hard to match right now because in Discord, these corners are rounded.

[3:07] If we just come here and add rounded to our bar, this is not going to work because it's rounding all four corners. Fortunately, we can use the rounded R-class to round just the right side. Now we're back in business. Let's increase the height here a little bit.

[3:24] Three, four, still a little short, five. Five seems to do the trick. Now let's work on this hover treatment. We can see in Discord when we hover the button, the indicator here scales out and fades out. Then it scales up and fades in when we mouse over the button.

[3:46] Let's get the fading out working first. We can use opacity zero, hover opacity 100. Now when we hover the bar, we see it pops in, but it's not fading in. We can achieve that easily using transition all and duration 200 to match our treatment down here on the button.

[4:11] Now we have this nice fade in effect. Of course, in Discord, the bar doesn't fade in when we hover over the bar, it fades in when we hover over this link. Fortunately, Tailwind has our back here.

[4:23] If we want to trigger a class when we hover over some parent element, we give that parent element the group class, in this case our anchor tag, and then we just change this hover to group hover. That's going to be all we need to do to actually trigger this to fade in.

[4:43] Now we can see when our button transitions, our bar fades in as well. You'll actually notice there's a little discrepancy here. When we hover over this link, which takes up all this space, we're getting the fade in effect on our bar, but we're not getting the transition on our button.

[5:00] That's because the hover classes on this div are just using hover. If we switch them to group hover, that should fix that as well. If we hover any part of this parent link, we get everything fading in and transitioning nicely, just like you'll see happen in Discord.

[5:17] The next part is this scaling effect. We'll see that the active indicator here scales down towards the left when we mouse away from the button. Well, we can achieve that pretty easily using Tailwind's scale utilities.

[5:31] Let's start it off at scale zero, and when we have the group hover, we'll apply scale 100. Now this is scaling in and out, and it looks almost right, but there's something a little off.

[5:49] If we come here and find duration 200 and slow this down just a little bit, we'll see that as this is scaling, it's actually scaling about the middle of the container and that's not what we want. We want that left side to hug the left side of the page.

[6:08] This is because the transform origin by default is the center, but we want it to be left. We can use origin left to set the transform origin here to left. Now, if we hover over this, we'll see that this is working exactly like we expect. Let's change this duration 1,000 back to 200.

[6:33] Now this is looking really nice. Let's work on the active state. In Discord, once we click this button, we see the height of the bar basically grows a little bit, and it transitions smoothly, just like that.

[6:49] Let's do the same thing we did before and use an expression here for our class name, so we can apply different styles based on whether this button is active or not. I'll come here, turn this into an expression, and turn these into template strings, so we can use our variable here.

[7:12] We'll say router.path name is equal to the home route. We'll apply some classes. Otherwise, apply some other classes. Let's just grab all the classes for our inactive state. We know the height is going to be five. We want the scale to be zero.

[7:32] Then we want the opacity, the group hover opacity, and the group hover scale to come along here as well. If we take a look at this, we should have our inactive state back, but when we click on this, the bar goes away because we have no height.

[7:51] We can get it back to five, but that's not quite right. Let's pump it up to 8, 9, and 10 looks spot-on. Now we got the hover treatment here, and then we click, and look at that, the bar grows just like Discord. There's one final detail we're missing.

[8:19] Notice in Discord when we hover and click, if our mouse is pressed down, we get this little nudge downwards, and then we let go, and it nudges back. Our clone doesn't have this yet, but we can achieve this using the translate utilities that come with Tailwind.

[8:37] We don't want the bar to go down, which is what we've been working on here. Let's find the actual button. Right here at the end, let's add translate Y. This utility uses all the same values from the spacing scale, so let's just try one. You'll see that that nudges our button down.

[8:58] We only want this to take effect when the user's actually clicking on the button, so when the mouse is actively being pressed. This corresponds to a pseudo class in CSS called active, which we can use via the active prefix.

[9:17] Just like that, now we have this where when we click on it, the button translates down. Just a few more tweaks. First, we want that nudge to apply if we're clicking the link right here, not just this button. Let's go ahead and make this a group active.

[9:36] Now we see it nudges down even if we're outside of the bounds of the button. Second, if we pop over to Discord, we'll see this nudge is much smaller than our current nudge here.

[9:48] Fortunately, Tailwind has a few values below one, including a pixel value, which is just going to give us a one pixel nudge. That looks a lot closer. The final detail is that our nudge is actually transitioning because of this transition all class. Whereas in Discord, it's just a instant nudge. Let's fix this by just wrapping this button in a new div and moving our class here up to this new div.

[10:21] Since this doesn't have any transition on it, it should just give us an immediate nudge, and it does. That looks really dang close, and we've only used the default classes that come with Tailwind, so this is pretty cool. Let's take one more look zoomed out here.

[10:40] We'll take a look at the inactive state in Discord, and then over in our clone, looks really good. Then, when we go from inactive to active, it looks like this. Then in our clone. That is pretty awesome.

[11:01] I'm all surprised with just how far I can get using the default utilities that come with Tailwind, and we haven't even had to write a single line of custom CSS yet.

[11:10] Now you might be wondering about how best to maintain all this new markup that we've created to work well with Tailwind's composable utility classes. We'll be covering that in the next episode.

~ a minute ago

Member comments are a way for members to communicate, interact, and ask questions about a lesson.

The instructor or someone from the community might respond to your question Here are a few basic guidelines to commenting on

Be on-Topic

Comments are for discussing a lesson. If you're having a general issue with the website functionality, please contact us at

Avoid meta-discussion

  • This was great!
  • This was horrible!
  • I didn't like this because it didn't match my skill level.
  • +1 It will likely be deleted as spam.

Code Problems?

Should be accompanied by code! Codesandbox or Stackblitz provide a way to share code and discuss it in context

Details and Context

Vague question? Vague answer. Any details and context you can provide will lure more interesting answers!

Markdown supported.
Become a member to join the discussionEnroll Today