5

I am trying to create a layout with a header on top, underneath it a sidebar and the main content.

I would like to have the sidebar and the content view take over the vertical space left by the header. The problem is that the header can dynamically re-size so I cannot perform a calc(). My solution was to use the flexbox scheme.

I divided the viewport horizontally into two parts. One is the header and one is a wrapper for the sidebar and main content.

The sidebar is floated left and given a percentage of the width and the content is floated right and given the rest.

The problem is that I am trying to make the sidebar always be 100% height of the wrapper.

I tried height: 100% and min-height: 100% but these do not work.

I do not wish to absolutely position it since if the wrapper were to overflow with the main content, the sidebar would not expand accordingly.

Here is my pen: http://codepen.io/markt5000/pen/JXNXpW

As you can see the orange is the header and the red space is the wrapper with the sidebar and the content.

here is the layout

<div class="header">
</div>

<div class="row">

  <div id="sidebar">
  </div>

 <div id="main-content">
 </div>

</div>

Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
naughty boy
  • 2,089
  • 3
  • 18
  • 28

3 Answers3

6

There's no need for:

Flex properties have all the power you need to make the layout work. The key is to use flex: 1 to make items expand the full available length of the container.

So your header's height can be dynamic and the sidebar and main content can be made to consume whatever height remains. No scrollbars.

Here's your code with some revisions:

html { height: 100%; }

body {
  height: 100%;
  margin: 0;
  padding: 0;
}

.outer-flex-container {
  height: 100%;
  display: flex;
  flex-direction: column;  /* main flex container stacks items vertically */
}

.header {
  height: 80px;            /* demo purposes; from your original code */
  background-color: orange;
}

.nested-flex-container {
  display: flex;           /* inner flex container stacks items horizontally */
  flex: 1;                 /* KEY RULE: tells this second flex item of main container
                                  to consume all available height */
  align-items: stretch;    /* KEY RULE: default setting. No need to include. Tells
                                  children to stretch the full length of the container
                                  along the cross-axis (vertically, in this case). */
}

.sidebar {
  flex-basis: 20%;        /* set width to 20% */
  background-color: aqua;
}

.content {
  flex: 1;                /* set width to whatever space remains */
  background: magenta;
}
<div class="outer-flex-container">

     <div class="header">HEADER</div><!-- main flex item #1 -->

     <div class="nested-flex-container"><!-- main flex item #2 -->
    
          <div class="sidebar">SIDEBAR</div><!-- inner flex item #1 -->
    
          <div class="content">MAIN CONTENT</div><!-- inner flex item #2 -->
    
     </div><!-- close inner flex container -->

</div><!-- close outer flex container -->

Revised Codepn

Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
  • 1
    Yep, the only modification was to set min-height so it doesn't collapse when there is no content and it works like a charm. Thanks.. http://codepen.io/markt5000/pen/RaVRqX?editors=1100 – naughty boy Mar 23 '16 at 02:24
  • Not as useful when `content` is large, e.g 5 para [lorem ipsum](https://loremipsum.io/generator/?n=5&t=p). Where to add `overflow-y: auto;` to make header and sidebar remain in place? –  Jul 01 '19 at 23:04
  • Please post a codepen illustrating the problem, or consider posting a new question. @eric99 – Michael Benjamin Jul 01 '19 at 23:59
  • Just pasted some lorem ipsum paras into `.content`, here is the [pen](https://codepen.io/anon/pen/bPvKBE?editors=1100). The problem I see is that the scrollbar is on `html`, which scrolls the header off-page (which wouldn't happen with absolute positioning), but hiding scrollbar on `html` and enabling on `content` or `nested-flex-container` doesn't work - there's no scrollbar on inner elements. –  Jul 02 '19 at 00:18
  • However, this SO answer [Fill remaining vertical space with CSS using display:flex](https://stackoverflow.com/a/25098486/8745435), which seems pretty close to this one, does seem to work ok (although no sidebar). Am trying to figure out the difference. –  Jul 02 '19 at 00:18
  • I think I know why. But I'm on a mobile device right now and can't test. I'll get back to you when I'm back on a desktop. – Michael Benjamin Jul 02 '19 at 00:46
  • But check this out. https://stackoverflow.com/q/36247140/3597276 @eric99 – Michael Benjamin Jul 02 '19 at 00:47
  • Cheers, that's a lot to digest but will do so. –  Jul 02 '19 at 01:26
  • @eric99, On `nested-flex-container`, either `overflow-y: auto` or `min-height: 0` will do the trick. As suspected, the explanation is in the link above. – Michael Benjamin Jul 02 '19 at 12:18
  • Thanks, I got it with `overflow-y: auto` and `height: 100%` on div.content. Not sure `min-height` is necessary (any more). –  Jul 02 '19 at 19:49
  • Same rule-of-thumb worked on my real app - make sure height is specified through all parents. In your sample above, parent of the snippet iFrame is `200px`, then `100%` all the way down until content - you omitted it there, but that's all that is required to get proper 'fixed position' from flex. –  Jul 02 '19 at 19:51
0

Is this what you're going for? http://codepen.io/Shambolaz/pen/xVdVyd

.view .row
{
  flex: 1 1 auto;
  background:red;
  height: 90%;
}
Ber
  • 695
  • 1
  • 11
  • 17
  • no, the problem is that I can't set the height of the .row since the header is resizable in height (due to its contents), and setting the height to 90% means that the header should be exactly 10% to cover 100% of the screen – naughty boy Mar 22 '16 at 23:52
  • to put is in simple terms, the header will have a height x and the wrapper should have the rest of the height to cover 100% of the height left in the viewport. In cases where the content is bigger then the wrapper should stretch to fit the contents and the sidebar should do so as well. – naughty boy Mar 22 '16 at 23:53
0

When content is larger than it's element, to get true 'fixed position' behavior add overflow: auto to the content element.

Also make sure height is concretely specified for all parents of the content element.

By that I mean there must be an ancestor element that has a specified height (either fixed px or 100vh).

Stack Overflow puts the snippet in an iFrame, which has a fixed-height parent, so the elements using height: 100% have something to calculate from.

We can therefore just add height: 100% to the content div, and the scrollbar will show up there.

This is the modified pen (also has a fixed height ancestor). You can experiment by removing the height CSS rules at various points, and see the scrollbar move up the element tree.

html { height: 100%; }
body {
  height: 100%;
  margin: 0;
  padding: 0;
}

.outer-flex-container {
  display: flex;
  flex-direction: column;  
  height: 100%;
}

.header {
  height: 80px;            
  background-color: orange;
}

.nested-flex-container {
  display: flex;          
  flex: 1;
}

.sidebar {
  flex-basis: 20%;       
  background-color: aqua;
}

.content {
  flex: 1;                
  background: magenta;
  overflow-y: auto;     
  height: 100%;
}
<div class="outer-flex-container">

     <div class="header">HEADER</div><!-- main flex item #1 -->

     <div class="nested-flex-container"><!-- main flex item #2 -->
    
          <div class="sidebar">SIDEBAR</div><!-- inner flex item #1 -->
    
          <div class="content">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Porttitor eget dolor morbi non arcu risus quis varius quam. Commodo viverra maecenas accumsan lacus. Vitae elementum curabitur vitae nunc sed velit dignissim. Auctor urna nunc id cursus metus aliquam eleifend. Bibendum ut tristique et egestas. Orci phasellus egestas tellus rutrum tellus pellentesque eu tincidunt. Diam maecenas ultricies mi eget mauris pharetra et. Ultricies mi eget mauris pharetra. Nibh mauris cursus mattis molestie.
            <br/>
            Urna neque viverra justo nec ultrices dui sapien. Diam vulputate ut pharetra sit amet aliquam id diam maecenas. Nunc non blandit massa enim nec dui nunc. Amet mattis vulputate enim nulla. Nisl condimentum id venenatis a condimentum vitae sapien. Magna sit amet purus gravida quis blandit turpis. Sed turpis tincidunt id aliquet risus. Aliquet lectus proin nibh nisl condimentum id venenatis a. Vitae purus faucibus ornare suspendisse sed. Sit amet commodo nulla facilisi nullam. Egestas fringilla phasellus faucibus scelerisque eleifend. Facilisi etiam dignissim diam quis enim lobortis scelerisque fermentum. Viverra adipiscing at in tellus integer feugiat. Scelerisque eu ultrices vitae auctor eu augue. At urna condimentum mattis pellentesque.
            <br/>
            Quisque id diam vel quam elementum pulvinar etiam non quam. Morbi tempus iaculis urna id volutpat lacus laoreet non curabitur. Diam quis enim lobortis scelerisque fermentum dui. Tortor id aliquet lectus proin nibh. Pellentesque pulvinar pellentesque habitant morbi tristique senectus et netus. Egestas fringilla phasellus faucibus scelerisque. Venenatis a condimentum vitae sapien pellentesque habitant. Quis vel eros donec ac odio tempor orci. Ultrices sagittis orci a scelerisque. Ligula ullamcorper malesuada proin libero nunc consequat interdum. Dis parturient montes nascetur ridiculus mus mauris. Nisl vel pretium lectus quam id leo in vitae. Euismod elementum nisi quis eleifend quam adipiscing vitae. Mattis vulputate enim nulla aliquet porttitor lacus luctus accumsan. Urna porttitor rhoncus dolor purus non. Lobortis mattis aliquam faucibus purus in massa tempor nec. Risus pretium quam vulputate dignissim suspendisse in. Malesuada bibendum arcu vitae elementum curabitur. Quisque id diam vel quam elementum pulvinar. A erat nam at lectus urna duis convallis.
            <br/>
            Nulla facilisi nullam vehicula ipsum. Nibh ipsum consequat nisl vel pretium lectus quam id leo. Morbi tristique senectus et netus et malesuada fames ac turpis. Quis imperdiet massa tincidunt nunc pulvinar sapien. Amet volutpat consequat mauris nunc congue nisi vitae. Feugiat sed lectus vestibulum mattis ullamcorper. Pharetra magna ac placerat vestibulum lectus. Sed faucibus turpis in eu mi bibendum neque egestas. A condimentum vitae sapien pellentesque habitant. Mi bibendum neque egestas congue quisque egestas diam. Vulputate odio ut enim blandit volutpat maecenas volutpat blandit. Lacus luctus accumsan tortor posuere ac ut.
            <br/>
            Sit amet cursus sit amet dictum. Sem integer vitae justo eget magna fermentum iaculis eu non. Etiam dignissim diam quis enim lobortis scelerisque fermentum dui faucibus. Congue mauris rhoncus aenean vel elit scelerisque mauris pellentesque pulvinar. Facilisis gravida neque convallis a cras semper. Nullam vehicula ipsum a arcu. Sed egestas egestas fringilla phasellus faucibus scelerisque eleifend donec pretium. Et odio pellentesque diam volutpat commodo sed egestas egestas. Velit aliquet sagittis id consectetur. Faucibus vitae aliquet nec ullamcorper. In iaculis nunc sed augue lacus viverra. Vitae semper quis lectus nulla at volutpat diam ut venenatis. Et malesuada fames ac turpis. Felis imperdiet proin fermentum leo vel. Fringilla est ullamcorper eget nulla facilisi etiam dignissim. Quis varius quam quisque id diam vel quam. Ornare arcu dui vivamus arcu felis bibendum ut. Turpis massa sed elementum tempus egestas sed. Morbi tincidunt augue interdum velit euismod in pellentesque massa placerat. Arcu ac tortor dignissim convallis aenean et tortor.
          </div><!-- inner flex item #2 -->
    
     </div><!-- close inner flex container -->

</div><!-- close outer flex container -->