5

The following HTML is simple and does what I want. The green body stretches downward to fill the window.

<body style="margin:0">
    <div style="height:100%;display:flex;flex-direction:column">
        <div style="background:#d0d0ff">
            This is a header
        </div>
        <div style="background:#d0ffd0;flex-grow:1">
            This is the body.
        </div>
    </div>
</body>

But if I replace that body text with some flex columns, and I give them height:100% because I want them to stretch to the bottom, the newdiv actually gets a height greater than 100% of it's container and causes everything to scroll. Why doesn't 100% mean 100% here?

<body style="margin:0">
    <div style="height:100%;display:flex;flex-direction:column">
        <div style="background:#d0d0ff">
            This is a header
        </div>
        <div style="background:#d0ffd0;flex-grow:1">
            <!-- The new part -->
            <div id='newdiv' style="display:flex;flex-direction:row; height:100%">
                <div style="background:#ffd0d0"> Col 1 </div>
                <div> Col 2 </div>
            </div>
        </div>
    </div>
</body>

enter image description here

Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
Rob N
  • 15,024
  • 17
  • 92
  • 165

4 Answers4

4

The reason you're getting the vertical scrollbar is because you're telling the div parent of col1 and col2 to be height: 100%. This by itself gives it the full height of the viewport.

From your code:

<div id='newdiv' style="display:flex; flex-direction:row; height:100%">
    <div style="background:#ffd0d0"> Col 1 </div>
    <div> Col 2 </div>
</div>

Except this div has a sibling: the header div, which is also taking up space.

So when the browser does it's height calculation, here is the result:

100% + (computed height of header div) > viewport height = vertical scrollbar

Instead of using defined heights, consider letting flexbox do the work. By default, flex items expand the full length of the container along the cross-axis.

So by simply declaring display: flex, child elements will expand to fill all available space (with no vertical scroll). But since a height rule will override this flex setting, we need to remove height: 100% from any flex items.

html, body { height: 100%; }
<body style="margin:0">
    <div style="height:100%;display:flex;flex-direction:column">
        <div style="background:#d0d0ff">
            This is a header
        </div>
        <div style="background:#d0ffd0;flex-grow:1; display: flex;"><!--adjustment here-->
            <div id='newdiv' style="display:flex;"><!--adjustment here-->
                <div style="background:#ffd0d0; display: flex;"> Col 1 </div>
                <div> Col 2 </div>
            </div>
        </div>
    </div>
</body>

There are two adjustments to the original code.

  • added display: flex
  • removed height: 100%

Fiddle Demo

Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
  • Your code works, but my question is really about *why*, so let me understand: you said height:100% makes it 100% of viewport. That would make sense, but I thought height:100% meant 100% of parent block element? http://www.w3schools.com/cssref/pr_dim_height.asp – Rob N Feb 07 '16 at 14:25
  • Percentage heights work based on the height of the parent. You are correct. Except if the parent is also a percentage height, it must look to its parent. This cycle continues until it reaches the root element (`html { height: 100%; }`). That's the viewport height. So unless you set, let's say, `height: 250px` to a parent, all percentage heights will look all the way up the tree for guidance. – Michael Benjamin Feb 07 '16 at 14:27
  • Okay, but that's not what my example code did. The parent of `newdiv` had no `height` style. – Rob N Feb 07 '16 at 14:42
  • Your example code didn't reproduce the image you posted. The `height: 100%` was doing nothing. This is your code: https://jsfiddle.net/tdckcxhh/2/ – Michael Benjamin Feb 07 '16 at 14:45
  • Sorry my friend. There's no bug in the fiddle (which is powered by the browser it uses). The behavior is the same in Chrome, FF and IE11. It adheres to the standard. See my answer here: http://stackoverflow.com/a/31728799/3597276 – Michael Benjamin Feb 07 '16 at 14:53
  • Maybe there's already an `html, body { height: 100%}` declared in the HTML or CSS file you're using. – Michael Benjamin Feb 07 '16 at 14:54
  • Sorry I shouldn't say 'bug'. Just 'behavior difference'. On OS X 10.11.3, Chrome and Safari behave like my screenshot. But FF behaves better, but also different from the fiddle link. In FF the pink and green stretch to bottom. In the fiddle they don't. If you're not testing in same environment, I can't prove it to you. – Rob N Feb 07 '16 at 15:01
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/102837/discussion-between-michael-b-and-rob-n). – Michael Benjamin Feb 07 '16 at 15:02
0

I would do it like this. demo

<body>
   <header>Header</header>
   <div class="body">
     <aside>abc</aside>
     <div class='inner'>content here</div>
   </div>
</body>

In your css

html,body{
  height: 100%;
}

body{
  display: flex;
  flex-direction: column;

}


.body{
  flex-grow:1;
  display: flex;
  align-items: stretch;

}

.inner{
  flex-grow: 1;
}

and this gives you a better html structure and maintainability

Louie Almeda
  • 5,366
  • 30
  • 38
0

What about this? - http://codepen.io/arianalynn/pen/WragJP?editors=1010

<style>
 body, html {margin:0;height:100%;width:100%;padding:0}
</style>
<body>
  <div style="height:100%;display:flex;flex-direction:column">
    <div style="background:#d0d0ff">
      This is a header
    </div>
    <div style="background:#d0ffd0;flex-grow:1;display:flex;flex-direction:row; height:100%;-webkit-align-items:stretch">
      <div style="background:#ffd0d0"> Col 1 </div>
      <div style="background:red"> Col 2 </div>
    </div>
  </div>
</body>
Leena Lavanya
  • 333
  • 1
  • 10
0

I have updated your code try if this helps you. set the height to 100vh https://jsfiddle.net/ok20071g/1/

Sagun Gautam
  • 470
  • 6
  • 20