Archeg
Archeg

Reputation: 8462

Flexbox: stretch sidebar height to the parent

How to properly stretch a child to parent's height? I've tried a lot of variants I found (many quite complicated), but it never worked for me. I would prefer to do this with flex-box, as that seems the newest method. Here is my try:

<div class="main h-100">
  <nav class="navbar navbar-expand-lg navbar-dark bg-primary">
    <a href class="navbar-brand">Menu</a>
  </nav>
  <div class="container-fluid h-100">
    <div class="row h-100">
      <div class="col-xs-2 bg-light h-100 pr-3 menuContainer">
        <button class="btn btn-outline-primary mt-3 btn-sm btn-block"> Test </button>
        <nav class="navbar navbar-light list">
          <ul class="navbar-nav flex-column">
           <li class="nav-item"><a href="#" class="nav-link">A1</a></li>
           <li class="nav-item"><a href="#" class="nav-link">A1</a></li>

          </ul>
        </nav>
      </div>
      <div class="col-xs-10 p-0">
        Content
      </div>
    </div>
  </div>

body {
  height: 100vh;
}

.bg-light {
  background-color: green !important;
}

.list {
  overflow-y: auto;
  height: 100%;
  align-items:start
}

.menuContainer {
  display: flex;
  flex-flow: row wrap;
}

.list {
  flex: 1;
  background-color: red;
}

http://jsfiddle.net/x1hphsvb/2065/

In the end I'd like to remove the scroll, so that the menu (red box) starts where it starts now and ends exactly where the screen end is.

The aim is also to be able to put anything instead of Content with height: 100% so it does the same.

Both content and menu can be bigger - in that case I expect them to add a scroll on it's own - I use overflow-y: auto for that.

Upvotes: 1

Views: 2723

Answers (3)

Carol Skelly
Carol Skelly

Reputation: 362290

In Bootstrap 4.1 there is a flex-fill utility class for this purpose.

.flex-fill {
  flex: 1 1 auto;
}

In your case, add it to your container-fluid and you won't need all the h-100s. Also, make the container fluid d-flex so that flex-fill can also be applied on the row.

<div class="main h-100 d-flex flex-column">
  <nav class="navbar navbar-expand-lg navbar-dark bg-primary">
    <a href class="navbar-brand">Menu</a>
  </nav>
  <div class="container-fluid flex-fill d-flex">
    <div class="row flex-fill">
      <div class="col-xs-2 bg-light pr-3 menuContainer d-flex flex-column">
        <button class="btn btn-outline-primary mt-3 btn-sm btn-block"> Test </button>
        <nav class="nav navbar-light list">
          <ul class="navbar-nav flex-column">
           <li class="nav-item"><a href="#" class="nav-link">A1</a></li>
           <li class="nav-item"><a href="#" class="nav-link">A1</a></li>
          </ul>
        </nav>
      </div>
      <div class="col-xs-10 p-0">
        Content
      </div>
    </div>
  </div>
</div>

https://www.codeply.com/go/GEiw0PABgi

Also, note that col-xs-* is col-* in Bootstrap 4 as the -xs infix has been removed. Here's a simplified example w/o the extra CSS.

Related questions: Bootstrap 4 Navbar and content fill height flexbox

Upvotes: 1

Michael Benjamin
Michael Benjamin

Reputation: 371013

You're getting an overflow because you're giving many (if not all) of your elements height: 100%. It's coming with the Bootstrap code:

.h-100 {
    height: 100% !important;
}

As a result, when there is more than one element in a container, the siblings overflow the parent.

I would remove height: 100% from elements that you want to have fill the height of the container. Flexbox offers a more efficient method.

When you set display: flex on an element it applies align-items: stretch on the child elements. This means that the children will automatically expand to fill the height of the container.

Set a height on one element (i.e., an ancestor). Then keep adding display: flex to each child down the HTML structure. There is no problem nesting flex containers.

Upvotes: 2

nanobar
nanobar

Reputation: 66325

http://jsfiddle.net/x1hphsvb/2083/

html, body {
  height: 100%;
}

.bg-light {
  background-color: green !important;
}

.list {
  overflow-y: auto;
  align-items:start
}

.menuContainer {
  display: flex;
  flex-direction: column;
}

.list {
  flex: 1;
  background-color: red;
}

.site-content {
  height: calc(100% - 56px);
}

Key differences:

  • flex-direction: column on sidebar items.
  • Remove height 100% on .site-content, instead do calc(100% - 56px) which is the header height.

Upvotes: 2

Related Questions