Todd Hivnor
Todd Hivnor

Reputation: 305

How to set the height for a flexbox container so it uses the "remaining space"

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>

Upvotes: 10

Views: 80751

Answers (3)

Kush Daga
Kush Daga

Reputation: 136

Just in case someone else also facing this, I had a use case where inside a flex column, we wanted to take up the remaining space by the second element in the column, and inside that element there is an overflowing element.

Here is one way to solve it - https://play.tailwindcss.com/kbJVRVFvID

Essentially with flex-grow: 1 you should also give some random height to the child element so that it fills up the space.

Upvotes: 0

kevmetz
kevmetz

Reputation: 1

  • 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;

Upvotes: 0

Michael Coker
Michael Coker

Reputation: 53664

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>

Upvotes: 11

Related Questions