Opens in a new tab

Creating a Complex Layout Using CSS Flexbox: Two Sidebars with Content in the Middle

Creating a Complex Layout Using CSS Flexbox: Two Sidebars with Content in the Middle

A page with a sidebar on the left, the main content in the middle and another sidebar on the right is one of the oldest layouts on the web. Developers even gave it a nickname, the “holy grail” layout, because for years it was surprisingly hard to build well. You needed floats, negative margins and tricks to make the columns the same height.

With flexbox it takes a few lines. In this tutorial we will build a complete CSS flexbox two sidebars layout: a header, the three columns, a footer, sidebars that stay in view while you scroll, and a clean mobile version. Every piece of code is explained, so you can adapt it instead of just copying it.

What our CSS flexbox two sidebars layout includes

  • A header across the full width.
  • A left sidebar for navigation, fixed at 220px.
  • A main content area that takes all remaining space.
  • A right sidebar for extras like ads or related posts, fixed at 260px.
  • A footer that stays at the bottom of the screen, even on short pages.
  • On phones, everything stacks into one column with the main content first.

Step 1: The HTML

We put the main content before the sidebars in the HTML. This matters: search engines and screen readers read the HTML from top to bottom, so the most important content should come first. Flexbox will move the left sidebar into place visually.

<div class="page">
  <header class="site-header">My Website</header>

  <div class="layout">
    <main class="content">
      <h1>Article title</h1>
      <p>The main content goes here...</p>
    </main>

    <aside class="sidebar sidebar-left">
      <nav>Navigation links</nav>
    </aside>

    <aside class="sidebar sidebar-right">
      Related posts, newsletter signup...
    </aside>
  </div>

  <footer class="site-footer">Copyright 2026</footer>
</div>

Step 2: Keep the footer at the bottom

Before building the columns, we solve a smaller problem. On pages with little content, the footer floats halfway up the screen and looks broken. A vertical flex container fixes it:

.page {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}
.layout {
  flex: 1;  /* the middle part grows and pushes the footer down */
}

Here flex-direction: column stacks the header, the layout and the footer vertically. Because .layout has flex: 1, it takes all the spare height, so the footer always sits at the bottom of the window.

Step 3: Build the three columns

.layout {
  flex: 1;
  display: flex;   /* row direction by default: side by side */
  gap: 32px;
  max-width: 1280px;
  width: 100%;
  margin: 0 auto;
  padding: 24px 16px;
  box-sizing: border-box;
}

.sidebar-left {
  flex: 0 0 220px;
  order: 1;
}
.content {
  flex: 1;
  min-width: 0;
  order: 2;
}
.sidebar-right {
  flex: 0 0 260px;
  order: 3;
}

Let us go through the important lines:

  • display: flex on .layout puts the three areas side by side.
  • flex: 0 0 220px means “do not grow, do not shrink, be 220px wide”. The sidebars keep a fixed width no matter how wide the screen is.
  • flex: 1 on the content means “take whatever space is left”. On a 1280px wide layout the content gets roughly 700px; on a wider screen it grows.
  • order rearranges the areas visually. In the HTML the content comes first, but on screen the left sidebar shows first.
  • gap: 32px adds space between the columns without any margin tricks.
Do not skip min-width: 0. Flex items will not shrink below the width of their content by default. One long URL, a wide table or a code block inside the main content can push the whole layout off the screen. min-width: 0 allows the content column to shrink properly, and long content then scrolls or wraps inside it.

Step 4: Equal height columns

You do not need to do anything for this. Flex items stretch to the height of the tallest item by default (align-items: stretch), so if the sidebars have background colours, they will run all the way down next to the content. This alone used to need JavaScript or “faux column” background images.

Step 5: Sticky sidebars

On long articles, it is nice when the navigation stays visible as you scroll. Add this:

.layout {
  align-items: flex-start;  /* needed for sticky to work */
}
.sidebar {
  position: sticky;
  top: 24px;
}

Why align-items: flex-start? A sticky element can only move within its parent’s free space. When the sidebar is stretched to full height, it has nowhere to move, so it never sticks. Letting it keep its natural height gives it room. The trade-off is that the sidebars no longer stretch to full height, so choose between equal height backgrounds and sticky behaviour based on your design.

If a sidebar is taller than the screen, add max-height: calc(100vh - 48px); overflow-y: auto; so its own content can scroll.

Step 6: Make it responsive

Three columns need at least about 1000px to look comfortable. Below that, we change the layout in two stages.

/* Tablets: drop the right sidebar below the content */
@media (max-width: 1024px) {
  .layout {
    flex-wrap: wrap;
  }
  .sidebar-right {
    flex: 1 1 100%;
    order: 4;
  }
}

/* Phones: one column, content first */
@media (max-width: 768px) {
  .layout {
    flex-direction: column;
    align-items: stretch;
  }
  .sidebar-left,
  .sidebar-right {
    flex: none;
    width: 100%;
    position: static;
  }
  .content       { order: 1; }
  .sidebar-left  { order: 2; }
  .sidebar-right { order: 3; }
}

On tablets the left sidebar and the content stay side by side, while the right sidebar wraps onto its own row underneath. On phones everything stacks, with the main content at the top where readers expect it. We also turn off sticky positioning on phones, because sticky sidebars on a small screen just get in the way.

The complete CSS flexbox two sidebars code

* { box-sizing: border-box; }
body { margin: 0; font-family: system-ui, sans-serif; }

.page { display: flex; flex-direction: column; min-height: 100vh; }
.site-header, .site-footer { padding: 16px; background: #0f172a; color: #fff; }

.layout {
  flex: 1;
  display: flex;
  align-items: flex-start;
  gap: 32px;
  max-width: 1280px;
  width: 100%;
  margin: 0 auto;
  padding: 24px 16px;
}
.sidebar-left  { flex: 0 0 220px; order: 1; }
.content       { flex: 1; min-width: 0; order: 2; }
.sidebar-right { flex: 0 0 260px; order: 3; }
.sidebar { position: sticky; top: 24px; }

@media (max-width: 1024px) {
  .layout { flex-wrap: wrap; }
  .sidebar-right { flex: 1 1 100%; order: 4; position: static; }
}
@media (max-width: 768px) {
  .layout { flex-direction: column; align-items: stretch; }
  .sidebar-left, .sidebar-right { flex: none; width: 100%; position: static; }
  .content { order: 1; } .sidebar-left { order: 2; } .sidebar-right { order: 3; }
}

The same layout with CSS grid

Flexbox handles this layout well, but it is worth knowing the CSS grid version too, because it is even shorter for page level structure:

.layout {
  display: grid;
  grid-template-columns: 220px minmax(0, 1fr) 260px;
  grid-template-areas: "left content right";
  gap: 32px;
}
.sidebar-left  { grid-area: left; }
.content       { grid-area: content; }
.sidebar-right { grid-area: right; }

@media (max-width: 768px) {
  .layout {
    grid-template-columns: 1fr;
    grid-template-areas: "content" "left" "right";
  }
}

Notice minmax(0, 1fr): it is the grid equivalent of min-width: 0, for the same reason.

Which one should you pick? Use grid for the overall page skeleton when the structure is fixed, and flexbox for components inside it, like menus, card rows and buttons. Many modern sites use both together. That said, the flexbox version is perfectly fine for production, and it is easier to understand if you are new to CSS layout.

Testing checklist for your CSS flexbox two sidebars layout

  • Paste a very long URL into the content. The layout should not break.
  • Delete most of the content. The footer should still sit at the bottom of the window.
  • Resize the browser from wide to narrow and check both breakpoints.
  • Press Tab through the page. Keyboard focus should follow a sensible order.
  • Check on a real phone, not just a resized desktop browser.

New to flexbox? Start with our simpler guide on how to create columns using CSS flexbox, then come back to this one. Once both make sense, you can build almost any page layout you will meet in client work.