htmlcssflexbox

How to prevent flex item from overflowing container?


So, I need a page with a 100%-width header above and two blocks - aside and main - that fit remaining height below it in the parent block (its height - 100vh) and both lay on a horizontal baseline. Main may contain too much content so it needs to be scrollable along Y axis - only content inside it needs to be scrollable, other parts (header and sidebar) remain in their places. So I have this code (question continues after it):

body {
  margin: 0;
}

.fx-a {
  height: 100vh;
  width: 100%;
  display: flex;
  flex-direction: column;
}

.header {
  background: red;
}

.fx-b {
  flex-grow: 1;
  display: flex;
}

.aside {
  background: yellow;
  flex: 1;
}

.main {
  background: blue;
  flex: 3;
  overflow-y: scroll;
}

.test {
  margin-top: 100px;
}
<div class="fx-a">
  <header class="header">
    <h2>Title</h2>
  </header>
  <div class="fx-b">
    <aside class="aside"></aside>
    <main class="main">
      <div class="test">a</div>
      <div class="test">a</div>
      <div class="test">a</div>
      <div class="test">a</div>
      <div class="test">a</div>
      <div class="test">a</div>
      <div class="test">a</div>
      <div class="test">a</div>
      <div class="test">a</div>
      <div class="test">a</div>
      <div class="test">a</div>
    </main>
  </div>
</div>

But when content in the main grows, main also grows, and sidebar does as well because it's in the same flex box. Then, when I try to scroll, the whole page scrolls, that's not what I need. How can it be fixed with only HTML and CSS?

P.S. I know I could set the height to header manually and then subtract it from 100vh to set the aside and main height, but I think it's not the case - height of the header depends on content inside of it.


Solution

  • Set overflow: hidden on .fx-b to force the container to limit its child:

    body {
      margin: 0;
    }
    
    .fx-a {
      height: 100vh;
      width: 100%;
      display: flex;
      flex-direction: column;
    }
    
    .header {
      background: red;
    }
    
    .fx-b {
      flex-grow: 1;
      display: flex;
      overflow: hidden;
    }
    
    .aside {
      background: yellow;
      flex: 1;
    }
    
    .main {
      background: blue;
      flex: 3;
      overflow-y: scroll;
    }
    
    .test {
      margin-top: 100px;
    }
    <div class="fx-a">
      <header class="header">
        <h2>Title</h2>
      </header>
      <div class="fx-b">
        <aside class="aside"></aside>
        <main class="main">
          <div class="test">a</div>
          <div class="test">b</div>
          <div class="test">c</div>
          <div class="test">d</div>
          <div class="test">e</div>
          <div class="test">f</div>
          <div class="test">g</div>
          <div class="test">h</div>
          <div class="test">i</div>
          <div class="test">j</div>
          <div class="test">k</div>
        </main>
      </div>
    </div>