7

I'm struggling to understand how flexbox containers interact with other blocks. With just a flexbox on my page, I can do what I want. But when I mix in other page elements, things get weird. The problem seems to be space allocation.

My flexbox container seems to need an explicit height. If I don't specify that, I don't get the wrapping behavior. I'm not sure how to specify the height of the flexbox container.

If I set the height of the flexbox container to 100%, it wraps as desired but I am stuck with a scrollbar to nowhere: I've allocated more than 100% of height. I want to allocate 100px above the flexbox container. So I need to make the flexbox container height something like 100% - 100px. I can't mix absolute and relative measurements. And looking down the road, I would prefer not to have to do this math at all, it will become a maintenance hassle.

Below is an example of where things go wrong for me. I want to have some instructions at the top of the page. The instructions should span the width of the page. In the space below, I want a collection of buttons. The buttons should wrap to use multiple columns, as needed.

I can make it work by button the instructions inside the flexbox container. But then, it won't have 100% with like I want, it will get jumbled up with my buttons.

<html>
    <head>
        <style>
            *  {
                margin: 0;  
                padding: 0;
                border: 1px solid #A00;
            }
            .instructions {
                height: 100px;
                background: linear-gradient(to bottom, #ffffff 0%, #999 100%);  
            }
            .container {
                display: flex;
                flex-direction:  column;
                flex-wrap: wrap;  
                height: 80%;        
            }
            .button {
                width: 200px;
                height: 50px;
                margin: 10px;
                background: linear-gradient(to bottom, #ffffff 0%, #BBB 100%);          
                border: 1px solid #CCC;
                text-align: center;
            }
        </style>
    </head>
    <body>
        <div class="instructions">Instructions  go here.</div>
        <div class="container">            
            <div class="button">This is Button 1</div>
            <div class="button">Thar be Button 2</div>
            <div class="button">Yarr, button 3</div>
            <div class="button">Hey that is a nice looking button.</div>
            <div class="button">Click Me!</div>
        </div>
    </body>
</html>
Todd Hivnor
  • 175
  • 1
  • 4
  • 12
  • is this what you try to do ? http://codepen.io/gc-nomade/pen/jBYbYZ . Can be inspired from http://stackoverflow.com/questions/25098042/fill-remaining-vertical-space-with-css-using-displayflex/25098486 or http://stackoverflow.com/questions/23090136/how-can-i-make-my-flexbox-layout-take-100-vertical-space/23090449 if not duplicate – G-Cyrillus Mar 18 '17 at 00:10

2 Answers2

10

You have to give the section a height to limit it to cause the buttons to wrap, otherwise the flex element will just grow to fit the height of whatever's inside of it.

I would use height: calc(100vh - 100px) on the flex container to make it take up all of the available space.

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

.instructions {
  height: 100px;
  background: linear-gradient(to bottom, #ffffff 0%, #999 100%);
}

.container {
  display: flex;
  flex-direction: column;
  flex-wrap: wrap;
  height: calc(100vh - 100px);
}

.button {
  width: 200px;
  height: 50px;
  margin: 10px;
  background: linear-gradient(to bottom, #ffffff 0%, #BBB 100%);
  border: 1px solid #CCC;
  text-align: center;
}
<div class="instructions">Instructions go here.</div>
<div class="container">
  <div class="button">This is Button 1</div>
  <div class="button">Thar be Button 2</div>
  <div class="button">Yarr, button 3</div>
  <div class="button">Hey that is a nice looking button.</div>
  <div class="button">Click Me!</div>
</div>

Alternatively, you could limit the height of body to 100vh, make it display: flex; flex-direction: column and set flex-grow: 1 on .container so it will take up the available space.

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

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

.instructions {
  height: 100px;
  background: linear-gradient(to bottom, #ffffff 0%, #999 100%);
}

.container {
  display: flex;
  flex-direction: column;
  flex-wrap: wrap;
  flex-grow: 1;
}

.button {
  width: 200px;
  height: 50px;
  margin: 10px;
  background: linear-gradient(to bottom, #ffffff 0%, #BBB 100%);
  border: 1px solid #CCC;
  text-align: center;
}
<div class="instructions">Instructions go here.</div>
<div class="container">
  <div class="button">This is Button 1</div>
  <div class="button">Thar be Button 2</div>
  <div class="button">Yarr, button 3</div>
  <div class="button">Hey that is a nice looking button.</div>
  <div class="button">Click Me!</div>
</div>
Michael Coker
  • 52,626
  • 5
  • 64
  • 64
  • Thanks, your comment about why the behavior exists makes sense. Wow there is so much to learn about CSS! I didn't realize I could use calc(). I think I will try the second solution, that seems like it will take more thinking due to nested flexboxes. But probably more maintainable longer term. I want to set things up so they 'just work' down the road. Anyway, thanks for you help, Michael! – Todd Hivnor Mar 18 '17 at 00:18
  • I know it is an old post but this answer saved me a whole lot of headache. I struggled for 24 hours trying to find a fix for a similar issue. Thank you @Michael – phagyrhe Aug 04 '20 at 08:03
0
  • using flex-grow: 1 is the new paradigm and its best to think in flex

  • using calc(100vh - 100px) adds in an undesirable fixed value of 100px

  • this value is not allowed to change without re-editing the css

  • if you do want a fixed height, express the height in rem units

  • ideally use a 100vh container and make it a giant flex column

    CSS: display: flex; flex-direction: column; justify-content: flex-start; align-items: center; min-height: 100vh;

  • then add child divs for your content using flex: 1

    CSS: display: flex; flex-direction: column; justify-content: flex-start; align-items: center; width: 100%; flex: 1;

  • or in the case of a fixed height for the instructions, use rem units

    CSS: display: flex; flex-direction: column; justify-content: flex-start; align-items: flex-start; width: 100%; height: 6.25rem;

kevmetz
  • 1
  • 2
  • NOTE: *** Ultimately all developers should spend a week-end setting up divs and conducting experiments with flex and grid to under the complexities of the model – kevmetz Apr 21 '23 at 17:46