Building the Channel Header with Flexbox Shrink and Truncating Text

Sam Selikoff
InstructorSam Selikoff
Share this video with your friends

Social Share Links

Send Tweet

Learn how to use the flexbox-shrink utility to choose which parts of our multi-column layout shrink or expand to accommodate the available space. Use the truncate utility to add ellipses when the channel description is too long.

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

  1. Begin
  2. End

Sam Selikoff: [0:00] Now that we have our channel nav working over here, we can actually make this channel header dynamic. If we come over to Discord, we'll see a lot of elements here. Of course, as we navigate, they all change.

[0:11] The title updates, the description updates, and then we have these elements right here. Let's start with getting the title to be dynamic. Right now, we're rendering this static text right here in line 66.

[0:23] To actually get the title, we're going to again poke into our data.js file right here. We'll see that each channel has a label and a description. We want to use the channel ID in the URL in order to get that. I'll just paste in some code right here.

[0:42] This should look pretty familiar to what we've seen before. We're grabbing the router. We're going to go ahead and use the router queries server ID to get the server again, which is just a blob of JSON here for the current server.

[0:56] Then we're going to get all of the categories channels, flatten them, and then find the channel that matches the CID from the router. That will give us a blob of JSON that looks like this. This channel variable right here is going to have a label property.

[1:17] We can come back down here to where we were hardcoding this in and change it with channel.label. When we click around, we'll see that that title updates. At this point, we've built a lot of UI that looks a lot like this. I'm going to paste in all of these buttons and this text.

[1:38] We're going to focus on the interesting part, which is this description. Let's come back to our clone. Here's our label. Right inside this div, I'll paste in all this code. Let's see how it lines up. Looks like we have a little bit of extra padding here.

[1:55] Let's change this px-3 on the wrapper to px-2. It looks like these things are lining up with the exception of the search box and the description. Just take a look at what I pasted in. Again, this is pretty standard stuff at this point. We have a flex container.

[2:13] We're using items-center. All these elements line up nicely, vertically. We've got the hashtag icon with the fixed width and height. We have some typographic styles. Really nothing fancy going on here.

[2:27] We're wrapping all these buttons in a div and using margin left auto, which is going to create all of this margin here and push these far over to the right, which again works because we are in a flex container right here.

[2:39] Then we just wrap each one of these icons in a button and give it a little hover treatment similar to what we see on Discord. For the interesting part is we want this description. Not every channel has a description.

[2:53] We can see here, if it doesn't have a description, we don't actually render that little vertical line and the description text. If we do, we have this little divider here and then we have the text. Let's come down here below the hashtag and channel title.

[3:10] We'll conditionally render here based on the channel's description. Let's start with this little vertical line here, right there. We'll just make a div with a width of one pixel. This has a height of 24 pixels, which is h-6. If we throw background white on it, then we should see it show up.

[3:31] We'll also give it a little bit of margin. Then the background opacity here is actually .06. Now that little divider line matches up nicely, Let's use another div for the channel.description. Because we have these two siblings, let's go ahead and wrap them in a fragment.

[3:56] Here we see our description is rendering. This description is text-small, font-medium, and its text-gray-200. Typographically, that looks good. We also want a little bit of margin on this. Now we can talk about the actual layout.

[4:20] The text here is wrapping in order to try to squeeze into the space that we have, but we don't want that. We want this always to be on a single line. There's a few ways to control whitespace in Tailwind. We could use whitespace-nowrap. That'll force it all to be on one line.

[4:40] Ultimately, we want this truncation behavior that we see over in Discord. If we change the size of this, you'll see that as the window grows, this is really the element that's growing to fill the available space.

[4:54] It's also shrinking to reserve space for these elements right here, and right here, and to preserve the width of the two sidebars. If we come back to our clone, we'll see that our flexbox layout system has given more room to the description here.

[5:11] It's pushing off some elements here and it's also making our sidebar smaller. We never actually want that. We need to learn how to tell our layout which of these columns we actually want to grow and shrink.

[5:23] If we collapse these, we can see right here is our channel selector, right here is our main channel viewer. Then our server nav is in the app.

[5:34] With Flexbox, the way to do this is to use the flex-shrink utilities. If we put this on our third column here, we'll see that nothing happens right away. This is because a lot of this content is text, and text has a minimum width to it, which Flexbox respects.

[5:52] We need to tell Flexbox here that, actually, the minimum width of this column should be zero so that you can shrink down to it if you need to. Now that we've done that, we'll see that we are keeping the reserved space for the first two columns. This one has shrunk, so we're in a better spot here.

[6:09] The problem is, this line of text is still taking precedence and pushing our icons over. Let's find our channel.description again. If we were to come here and add overflow-hidden and save it, now, we'll see that our layout doesn't scroll at all anymore. Our icons are now lining up perfectly with Discord.

[6:33] Here, you can see just these last two. Again, we don't have the search bar right now, but you can see the space is being reserved for this div right here and this div right here, and this is actually the one that is flexing.

[6:45] Again, controlling layout with flex is all about marking certain elements as able to be shrunk. When we have overflow-hidden, that's going to tell our layout that you can go ahead and shrink this text note down however far it needs to go.

[6:59] Finally, we want to add this truncation behavior, which fortunately comes in CSS, and there's even a Tailwind utility for it. If we add the truncate class, we'll see that we now have the ellipsis. If we change this to be a little bit more dynamic, we'll see that that works perfectly here.

[7:20] If I hover over this truncate class, we'll see that this is applying overflow-hidden and whitespace-nowrap, which is basically exactly how we got to this treatment on our own. Then it's also applying the text-overflow: ellipsis class here.

[7:32] This is one of the only utilities that applies multiple rules because this ellipsis property only makes sense alongside these other two. That means we can remove our whitespace-nowrap and remove the overflow-hidden, and we'll have exactly the same treatment.

[7:53] We can play around with this a little bit. We can make it bigger or smaller. We'll see that this all works. All the spacing is reserved for every other element. If we come up here to Announcements or some channel that doesn't have a description, it won't render anything.

[8:07] Let's try to compare it here again and see where we ended up. This looks pretty good. Again, our size is off because of that, but everything is looking quite nice right now. Now, we've got this dynamic header almost completely built.