cssflexbox

Prevent expansion of flex container - filling vertical space


I'm trying to make a layout with a sidebar that expands to the full height of the content area without increasing the size of that content area flex container. The menu has a set height of 50px and .container element must fill the remaining vertical space.

Layout without Sidebar (no issue):

https://codesandbox.io/p/sandbox/n2nr3l

This is the layout without the sidebar which is working fine, it is a menu at the top with the content container underneath filling the viewport. Next I put the sidebar in the content container which causes it to expand vertically which is the problem. The expansion of the content container causes the 100vh page container to have a scrollbar.

Layout with the Sidebar (expanding issue):

https://codesandbox.io/p/sandbox/zg672p?file=%2Fstyles.css%3A24%2C16

HTML:

<div class="page">
  <div class="menu">menu</div>
  <div class="container">
    <div class="main"></div>
    <div class="sidebar">
      <div class="content-item"></div>
      <div class="content-item"></div>
      <div class="content-item"></div>
    </div>
  </div>
</div>

CSS:

.page {
  display: flex;
  flex-direction: column;
  height: 100vh;
  background-color: orange;
}

.menu {
  width: 100%;
  height: 50px;
  background-color: lightblue;
  flex-shrink: 0;
}

.container {
  background-color: lightcoral;
  display: flex;
  flex-direction: row;
}

.sidebar {
  width: 300px;
  overflow-y: scroll;
}

.content-item {
  height: 400px;
  width: 90%;
  margin: 10px;
  background-color: white;
}

html,
body {
  padding: 0;
  margin: 0;
}

The sidebar needs to fill the remaining free vertical space and use a vertical scrollbar rather than causing expansion.


Solution

  • Consider applying min-height: 0 to the .container element. This declaration overrides the implicit min-height: min-content that children of vertical flex layouts have. This allows .container to shrink to fit in the remaining space, which in turn means the sidebar fits inside this remaining space.

    .page {
      display: flex;
      flex-direction: column;
      height: 100vh;
      background-color: orange;
    }
    
    .menu {
      width: 100%;
      height: 50px;
      background-color: lightblue;
      flex-shrink: 0;
    }
    
    .container {
      background-color: lightcoral;
      display: flex;
      flex-direction: row;
      min-height: 0;
    }
    
    .sidebar {
      width: 300px;
      overflow-y: scroll;
    }
    
    .content-item {
      height: 400px;
      width: 90%;
      margin: 10px;
      background-color: white;
    }
    
    html,
    body {
      padding: 0;
      margin: 0;
    }
    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <meta http-equiv="X-UA-Compatible" content="ie=edge" />
        <title>HTML + CSS</title>
        <link rel="stylesheet" href="styles.css" />
      </head>
      <body>
        <div class="page">
          <div class="menu">menu</div>
          <div class="container">
            <div class="main"></div>
            <div class="sidebar">
              <div class="content-item"></div>
              <div class="content-item"></div>
              <div class="content-item"></div>
            </div>
          </div>
        </div>
      </body>
    </html>