Scaffolding a multipanel layout

Scaffolding a multipanel layout

Use Tailwind's Flexbox utilities to make an application layout with fixed and flexible panels.

Video resources

Transcript

When scaffolding an app layout, I like to start from the outside in. So taking a look at Discord, I kind of see three main pieces here. We have the server selector, the channel selector, and then this main message area.

So let's come over to our app and just start with three new divs:

<div>
  <div>Servers</div>
  <div>Channels</div>
  <div>Main</div>
</div>

We'll have servers, channels, and our main area.

Now by default, these divs lie on top of each other, but we can use the flex utility class, which will give our app a flex layout with a default flex direction of row.

<div className="flex">
  <div>Servers</div>
  <div>Channels</div>
  <div>Main</div>
</div>

Now over in Discord, we can see the server selector is kind of the darkest gray, and then the channel selector is a little bit lighter, and the main is the lightest. So let's give our server selector a background of gray-800; channels will be background of gray-700, and the main area will be background gray-600. And we'll make the text white so we can read it.

<div className="flex text-white">
  <div className="bg-gray-800">Servers</div>
  <div className="bg-gray-700">Channels</div>
  <div className="bg-gray-600">Main</div>
</div>

Now let's make our parent container here a height of the full screen so that all of these divs fill up the available space:

<div className="flex h-screen text-white">
  <div className="bg-gray-800">Servers</div>
  <div className="bg-gray-700">Channels</div>
  <div className="bg-gray-600">Main</div>
</div>

Now, if we hop back over to Discord, we'll see that the server selector and the channel selector kind of have this fixed width. But as the user resizes the app, it's really this main area that takes up the available space. And Flexbox is perfect for this. We can tell our layout to have the main panel here take up all the available space using the flex-1 utility class:

<div className="flex h-screen text-white">
  <div className="bg-gray-800">Servers</div>
  <div className="bg-gray-700">Channels</div>
  <div className="flex-1 bg-gray-600">Main</div>
</div>

And now if we pop open the inspector, we can see it does just that.

So this is why I like Flexbox for application layouts. It's really easy to pick which panel should grow and shrink, and which ones should be fixed.

Now let's add just a little bit of padding to each one of these panels using the padding utilities. These utilities use Tailwind's default spacing scale, which starts with 0 for no padding, then goes to 1, which is just 4 pixels of padding. So you can see here it adds just a little bit of padding around servers. And then we can go to 2 for 8 pixels, three for 12, and so on. So we'll go with p-4 on all three of these panels:

<div className="flex h-screen text-white">
  <div className="bg-gray-800 p-4">Servers</div>
  <div className="bg-gray-700 p-4">Channels</div>
  <div className="flex-1 bg-gray-600 p-4">Main</div>
</div>

And now we're seeing our layout kind of start to come together.

Server panel

Next, let's just make a white div for a dummy server selector here, just so we can visualize this a little bit better. And the way we can make a white circle is just by using a new div here and we'll drop TW just so we have some content. We'll go ahead and make the background white and we'll make the text gray-800:

<div className="flex h-screen text-white">
  <div className="bg-gray-800 p-4">
    <div className="bg-white text-gray-800">TW</div>
  </div>
  <div className="bg-gray-700 p-4">Channels</div>
  <div className="flex-1 bg-gray-600 p-4">Main</div>
</div>

And we want to give this white box a certain size. So over here we can inspect one of these and see that these are 48 x 48 pixels. So we can explicitly set the width and height of our box to 48 pixels using the width and height utilities.

Now width uses the same spacing scale the padding does, so it starts off at 0; 1 is 4 pixels, which is really small; 2 is 8 pixels, and so on.

In our case, we want 12 for 48 pixels, and we'll also set the height to 12 as well:

<div className="h-12 w-12 bg-white text-gray-800">TW</div>

And that will give us our 48 pixel box.

Now we can use rounded to make this a rounded rectangle, and there's a rounded-full class, which will make it a complete circle:

<div className="h-12 w-12 rounded-full bg-white text-gray-800">TW</div>

And then to center the title, we can go ahead and use flex item-center justify-center, because that's just the easiest way to center this text:

<div className="flex h-12 w-12 items-center justify-center rounded-full bg-white text-gray-800">
  TW
</div>

So our server panel is looking pretty good. Let's come back to Discord and look at the channel selector.

Channel panel

Now, because these channels are all different lengths, we can just go ahead and use a fixed width on this panel right here, regardless of the content. And if we inspect this, we can see that this is 240 pixels.

So back in our clone, let's come to our channels panel and we'll use w-60 to get this to be 240 pixels:

<div className="flex h-screen text-white">
  <div className="bg-gray-800 p-4">{/* ... */}</div>
  <div className="w-60 bg-gray-700 p-4">Channels</div>
  <div className="flex-1 bg-gray-600 p-4">Main</div>
</div>

Now, if we come back and make this a little bit smaller here with the inspector, we can see that we still have the behavior where our main panel is flexing to take up the additional space, but our server and channel selectors remain fixed.

So you can see that Tailwind's default spacing scale is really nice to work with. Every unit on the scale is 4 pixels, and it's used across a lot of the common utilities like padding, margin, width, and height.

Now looking back at the channel selector, we see that there's actually this fixed header here, and as we scroll the channels, this part takes up the rest of the space.

So again, we have a good situation for Flexbox here. We want this entire panel to be a new flex parent, this to be a fixed height, and this part to flex to the available space.

So let's take a look and see how tall this is. It's 48 pixels. So we'll come back to our channels here and drop in two new divs, one for the header, and one for the channels:

<div className="w-60 bg-gray-700 p-4">
  <div>Tailwind CSS</div>
  <div>channels</div>
</div>

Now again, we want to make the parent a new flex parent, and we'll see that by default the direction is row so these are laid out next to each other, but we actually want these to be on top of each other, so we'll use flex-col to change the direction to column:

<div className="flex w-60 flex-col bg-gray-700 p-4">
  <div>Tailwind CSS</div>
  <div>channels</div>
</div>

And now let's just give our channels a background of black so we can kind of see this layout as we build it.

<div className="flex w-60 flex-col bg-gray-700 p-4">
  <div>Tailwind CSS</div>
  <div className="bg-black">channels</div>
</div>

Okay, first let's move the padding off of the parent. We'll drop it right here, and we'll also drop it on this panel:

<div className="flex w-60 flex-col bg-gray-700">
  <div className="p-4">Tailwind CSS</div>
  <div className="bg-black p-4">channels</div>
</div>

And now we can see we kind of have our two panels right here. But really it would be nice if conceptually this channels part stretched to fill the remaining space, even though we don't have a lot of content in there right now, again, just because that is kind of what's going on in Discord.

So we can do that just like before using the flex-1 utility:

<div className="flex w-60 flex-col bg-gray-700">
  <div className="p-4">Tailwind CSS</div>
  <div className="flex-1 bg-black p-4">channels</div>
</div>

And there it stretches out.

So let's remove background black, and we can add a bit of shadow here to the header using the shadow-md utility:

<div className="flex w-60 flex-col bg-gray-700">
  <div className="p-4 shadow-md">Tailwind CSS</div>
  <div className="flex-1 p-4">channels</div>
</div>

And now we have a nice little header treatment here, with a channel's panel that's ready for the rest of our content.

Main panel

If we look at the main panel, we'll see it's a similar treatment with this header, a little shadow, and then a scrollable main area.

So let's just copy this treatment. We'll come here, remove the padding, we'll put general here, and messages.

<div className="flex-1 bg-gray-600">
  <div className="p-4 shadow-md">general</div>
  <div className="flex-1 p-4">messages</div>
</div>

And again, we can drop a background black on our messages just to see that right now it's not filling up this whole space. But if we make this a flex parent and flex-col, it should do the trick:

<div className="flex flex-1 flex-col bg-gray-600">
  <div className="p-4 shadow-md">general</div>
  <div className="flex-1 bg-black p-4">messages</div>
</div>

So now if we resize this, we'll see that, you know, everything is flexing in the right direction. The things we want fixed, like the header and the width of these two panels over here, are staying the same. And Flexbox is doing a good job of laying out the rest of these things for us.

<div className="flex h-screen text-white">
  <div className="bg-gray-800 p-4">
    <div className="flex h-12 w-12 items-center justify-center rounded-full bg-white text-gray-800">
      TW
    </div>
  </div>
  <div className="flex w-60 flex-col bg-gray-700">
    <div className="p-4 shadow-md">Tailwind CSS</div>
    <div className="flex-1 p-4">channels</div>
  </div>
  <div className="flex flex-1 flex-col bg-gray-600">
    <div className="p-4 shadow-md">general</div>
    <div className="flex-1 p-4">messages</div>
  </div>
</div>

So that's kind of how I think about using Flexbox for app layouts. The Tailwind utilities make it really easy to tinker around because these little utilities are just doing one thing. It's easy to pull 'em on and off different panels, and it's also just a great way to practice and improve your skills with Flexbox.

Buy Tailwind Mastery

Buy the course

$149one-time payment

Get everything in Tailwind Mastery.

  • 2+ hours of video
  • 21 lessons
  • Private Discord
  • Summaries with code
  • Unlimited access to course materials

Lifetime membership

$199
access all coursesone-time payment

Lifetime access to all current and future premium Build UI courses, forever.

  • Access to all five Build UI courses
  • New videos added regularly
  • Refactoring videos on React
  • Private Discord
  • Summaries with code
  • Full access to all future Build UI courses

What's included

Stream or download every video

Watch every lesson directly on Build UI, or download them to watch offline at any time.

Live code demos

Access to a live demo of each lesson that runs directly in your browser.

Private Discord

Chat with Sam, Ryan and other Build UI members about the lessons – or anything else you're working on – in our private server.

Video summaries with code snippets

Quickly reference a lesson's material with text summaries and copyable code snippets.

Source code

Each lesson comes with a GitHub repo that includes a diff of the source code.

Invoices and receipts

Get reimbursed from your employer for becoming a better coder!