How can I make my flexbox layout take 100% vertical space?
Asked Answered
D

4

181

How can I tell a flexbox layout row consume the remaining vertical space in a browser window?

I have a 3-row flexbox layout. The first two rows are fixed height, but the 3rd is dynamic and I would like it to grow to the full height of the browser.

enter image description here

I have another flexbox in row-3 which creates a set of columns. To properly adjust elements within these columns I need them to understand the full height of the browser -- for things like background color and item alignments at the base. The major layout would ultimately resemble this:

enter image description here

.vwrapper {
    display: flex;
    flex-direction: column;
    flex-wrap: nowrap;
    justify-content: flex-start;
    align-items: stretch;
    align-content: stretch;
    //height: 1000px;
}
.vwrapper #row1 {
    background-color: red;
}
.vwrapper #row2 {
    background-color: blue;
}
.vwrapper #row3 {
    background-color: green;
    flex 1 1 auto;
    display: flex;
}
.vwrapper #row3 #col1 {
    background-color: yellow;
    flex 0 0 240px;
}
.vwrapper #row3 #col2 {
    background-color: orange;
    flex 1 1;
}
.vwrapper #row3 #col3 {
    background-color: purple;
    flex 0 0 240px;
}
<body>
    <div class="vwrapper">
        <div id="row1">
            this is the header
        </div>
        <div id="row2">
            this is the second line
        </div>
        <div id="row3">
            <div id="col1">
                col1
            </div>
            <div id="col2">
                col2
            </div>
            <div id="col3">
                col3
            </div>
        </div>
    </div>
</body>

I've tried adding a height attribute, which does work when I set it to a hard number but not when I set it to 100%. I understand height: 100% isn't working, because the content isn't filling the browser window, but can I replicate the idea using the flexbox layout?

Doucet answered 15/4, 2014 at 17:6 Comment(2)
Upvote for the visuals, how did you make em?Regeniaregensburg
OmniGraffle, and Pixelmator for touchups.Doucet
H
187

You should set height of html, body, .wrapper to 100% (in order to inherit full height) and then just set a flex value greater than 1 to .row3 and not on the others.

.wrapper, html, body {
    height: 100%;
    margin: 0;
}
.wrapper {
    display: flex;
    flex-direction: column;
}
#row1 {
    background-color: red;
}
#row2 {
    background-color: blue;
}
#row3 {
    background-color: green;
    flex:2;
    display: flex;
}
#col1 {
    background-color: yellow;
    flex: 0 0 240px;
    min-height: 100%;/* chrome needed it a question time , not anymore */
}
#col2 {
    background-color: orange;
    flex: 1 1;
    min-height: 100%;/* chrome needed it a question time , not anymore */
}
#col3 {
    background-color: purple;
    flex: 0 0 240px;
    min-height: 100%;/* chrome needed it a question time , not anymore */
}
<div class="wrapper">
    <div id="row1">this is the header</div>
    <div id="row2">this is the second line</div>
    <div id="row3">
        <div id="col1">col1</div>
        <div id="col2">col2</div>
        <div id="col3">col3</div>
    </div>
</div>

DEMO


EDIT, as mention by @Basj , the code can be shorten . We can also nowdays use grid widely implemented : Below an example with grid for the visitors :

body {
    height: 100vh;
    display: grid;
    grid-template-rows: auto auto 1fr;
    margin: 0;
    background-color: orange;
    grid-template-columns: 240px 1fr 240px;
}

[id^=row]{ grid-column: 1/-1 }

#row1 { background-color: red; }
#row2 { background-color: blue; }
#row3 { background-color: green; }
#col1 { background-color: yellow; }
#col3 { background-color: purple; }
<div id="row1">this is the header</div>
<div id="row2">this is the second line</div>
<div id="col1">col1</div>
<div id="col2">col2</div>
<div id="col3">col3</div>
Henderson answered 15/4, 2014 at 17:22 Comment(12)
Any way to do this while also having the content divs expand to fill their contents? Forked your example here.Josephus
@Josephus , use min-height for chrome instead height fiddle.jshell.net/Lhhh3wde/1Henderson
The JSFiddle is brokenedMccray
Here is the working codepen demo: codepen.io/mprinc/pen/JjGQvae and explanation in the similar question: https://mcmap.net/q/92554/-fill-remaining-vertical-space-with-css-using-display-flexScurf
fiddle replaced by a codepen that should not vanish, it's a copy of the snippet . Note that min-height is not needed anymore in today's chrome version.Henderson
Setting 100% to body, html and the container after that and so on definitely works.Fault
@Henderson If you put content in col2 that overflows the screen height and you scroll down, the columns are not growing. Can you fix that somehow?Kotz
@Kotz Sounds like that's a new question that you should post.Dangerous
Great! Here is a slightly simplified version: https://mcmap.net/q/136192/-how-can-i-make-my-flexbox-layout-take-100-vertical-spaceBickart
@Bickart okay, you only removed the OP's wrapper and obsolete CSS for chrome (notified by comments :) ) Also, grid should also be proposed to make a shorter CSS without the wrapper codepen.io/gc-nomade/pen/GRxdYwPHenderson
Yes @G-Cyrillus, it was a minimal modification - full credit to you for the solution :)Bickart
@Bickart its fine with me , i like better the grid display for main and complex layouts that now works everywhere .I do not dislike, flex, and float, which are efficient for their jobs ;) (nor column CSS or table display) We do have a really good bunch of tools for layouts nowdays.Henderson
D
27

set the wrapper to height 100%

.vwrapper {
  display: flex;
  flex-direction: column;

  flex-wrap: nowrap;
  justify-content: flex-start;
  align-items: stretch;
  align-content: stretch;

  height: 100%;
}

and set the 3rd row to flex-grow

#row3 {
   background-color: green;
   flex: 1 1 auto;
   display: flex;
}

demo

Difficulty answered 15/4, 2014 at 17:20 Comment(1)
In my case html, body, .wrapper { height : 100%; } is working. not only wrapper working.Odaniel
B
6

The accepted answer is very good, but I noticed the wrapper was not needed, as well as a few other CSS rules. Here is a minimal version:

html, body { height: 100%; }
body { display: flex; flex-direction: column; margin: 0; }
#row1 { background-color: red; }
#row2 { background-color: blue; }
#row3 { background-color: green; flex: 2; display: flex; }
#col1 { background-color: yellow; flex: 0 0 240px; }
#col2 { background-color: orange; flex: 1 1; }
#col3 { background-color: purple; flex: 0 0 240px; }
<div id="row1">this is the header</div>
<div id="row2">this is the second line</div>
<div id="row3">
    <div id="col1">col1</div>
    <div id="col2">col2</div>
    <div id="col3">col3</div>
</div>
Bickart answered 6/8, 2022 at 16:5 Comment(1)
To make it shorter you can even use the grid display nowdays ;) codepen.io/gc-nomade/pen/GRxdYwPHenderson
S
5

Let me show you another way that works 100%. I will also add some padding for the example.

<div class = "container">
  <div class = "flex-pad-x">
    <div class = "flex-pad-y">
      <div class = "flex-pad-y">
        <div class = "flex-grow-y">
         Content Centered
        </div>
      </div>
    </div>
  </div>
</div>

.container {
  position: fixed;
  top: 0px;
  left: 0px;
  bottom: 0px;
  right: 0px;
  width: 100%;
  height: 100%;
}

  .flex-pad-x {
    padding: 0px 20px;
    height: 100%;
    display: flex;
  }

  .flex-pad-y {
    padding: 20px 0px;
    width: 100%;
    display: flex;
    flex-direction: column;
  }

  .flex-grow-y {
    flex-grow: 1;
    display: flex;
    justify-content: center;
    align-items: center;
    flex-direction: column;
   }

As you can see we can achieve this with a few wrappers for control while utilising the flex-grow & flex-direction attribute.

1: When the parent "flex-direction" is a "row", its child "flex-grow" works horizontally. 2: When the parent "flex-direction" is "columns", its child "flex-grow" works vertically.

Hope this helps

Daniel

Subscript answered 20/5, 2019 at 23:31 Comment(4)
div overkill.Uttica
You can remove one of your flex-pad-y :)Eyetooth
Nice..! This is the only example which managed to make my "content" <div> (in between my header and footer) fill the entire screen height. All the other examples seem to ignore the "height:100%" attribute.Grecian
It is a cool solutions. I know John says above DIV overkill, but I do not agree. You need the four divs to utilise flex grow both horizontally and vertically (Vertically been the important one!). Glad I could help ! Having the four DIVs gives you a lot of flexibility. Once you start trying to remove DIVs , that flexibility starts to wither !Subscript

© 2022 - 2024 — McMap. All rights reserved.