Maxim
Maxim

Reputation: 53758

Force flexbox element not to take all vertical space

TL;DR: flex element with flex-direction: row takes all vertical space and prevents the scrollbar in its child.


The first fiddle shows what kind of UI I'd like to achieve: it's a page that stretches to the whole screen, both horizontally and vertically. It contains a header and a main <div>, which is a scrollable list of items. The container is thus a column flexbox. Note that it's width and height are just fine.

Now I want to add a sidebar to the main content, and flexbox seems to be perfect for this as well. I simply add one more <div id='main'> with flex-direction: row: see the second fiddle. The sidebar is shown fine, but here is a problem. The new <div id='main'> takes all vertical space, as a result, the items list never gets a scrollbar.

I have tried to limit the height <div id='main'> and it seems to work. But it's pretty inconvenient in terms of code, because the header is a separate component, so in general its height is unknown to the main component and I have calculate it before setting height: calc(100vh - ...).

Is there a pure CSS way to tell a flexbox container not to grow vertically? Or should I go back to good old table html?

Upvotes: 2

Views: 12266

Answers (2)

Pete
Pete

Reputation: 58432

I would do it like this (comments in css as to what I have changed):

* {
    box-sizing: border-box;
}

body {
  margin: 0;
  padding: 0;
}

#container {
  padding: 10px;
  background: #fefefe;
  display: flex;
  flex-direction: column;
  max-height: 100vh;
  overflow: hidden;
  /*remove flex grow and shrink - as parent is not flex, these have no effect*/
}

#header {
  padding: 10px;
  background: #e1eaec;
}

#items {
  flex-grow: 1;     /* change the width and height for flex grow */
  background: #eee;
  padding: 10px;
  overflow: auto;
}

.item {
  background: lightyellow;
  padding: 20px;
}

/* New */

#main {
  display: flex;
  flex-direction: row;
  flex-grow: 1;            /* remove flex-shrink and set grow to 1 */
  /* height: 300px; */
}

#sidebar {
  flex-basis: 20%;
  padding: 10px;
}
<div id='container'>
  <div id='header'>
    <h1>Header</h1>
  </div>
  <div id='main'>
    <div id='items'>
      <div class='item'>Lorem Ipsum</div>
      <div class='item'>Lorem Ipsum</div>
      <div class='item'>Lorem Ipsum</div>
      <div class='item'>Lorem Ipsum</div>
      <div class='item'>Lorem Ipsum</div>
      <div class='item'>Lorem Ipsum</div>
      <div class='item'>Lorem Ipsum</div>
      <div class='item'>Lorem Ipsum</div>
      <div class='item'>Lorem Ipsum</div>
      <div class='item'>Lorem Ipsum</div>
      <div class='item'>Lorem Ipsum</div>
      <div class='item'>Lorem Ipsum</div>
    </div>
    <div id='sidebar'>
      Sidebar
    </div>
  </div>
</div>

Upvotes: 1

3rdthemagical
3rdthemagical

Reputation: 5350

You can use code below if you want to have sidebar with full available height, fixed header and scrollable content.

body {
    margin: 0;
}

section {
  display: flex;
  flex-direction: column;
  height: 100vh;
}

header {
  flex: 0 0 auto;
  background: red;
  font-size: 2em;
  padding: .5em;
}

main {
  display: flex;
  flex: 1 1 auto;
}

content {
  flex: 1 1 auto;
  overflow-y: scroll;
}

aside {
  flex: 0 0 auto;
  padding: 20px;
  background: green;
}

div {
  border: 1px solid red;
  padding: 1em;
}
<section>
  <header>header</header>
  <main>
    <content>
      <div>div</div>
      <div>div</div>
      <div>div</div>
      <div>div</div>
      <div>div</div>
      <div>div</div>
      <div>div</div>
      <div>div</div>
      <div>div</div>
      <div>div</div>
      <div>div</div>
      <div>div</div>
      <div>div</div>
      <div>div</div>
      <div>div</div>
      <div>div</div>
      <div>div</div>
      <div>div</div>
      <div>div</div>
      <div>div</div>
      <div>div</div>
      <div>div</div>
      <div>div</div>
      <div>div</div>
      <div>div</div>
      <div>div</div>
      <div>div</div>
      <div>div</div>
      <div>div</div>
    </content>
    <aside>sidebar</aside>
  </main>  
</section>

Upvotes: 1

Related Questions