0

I'm having a terribly difficult time trying to get Bootstrap/Flexbox to play nice with a height restriction.

In my layout, I have a <main> element with a fixed height. In the actual app it's calculated so that the footer appears at the bottom of the screen, for demonstration it's fixed at 500px.

I want to put some arbitrary-length user data (between 1 and potentially up to 1000 lines according to API response) in a card. I would like the card to be constrained by the calculated height of its container, with a scrollbar in the card to navigate its contents. However, the card-body seems absolutely totally intent on just growing to contain all contents - I can't get any part of the hierarchy to be limited by the 500px height set on the <main> element.

Here's a simplified example. The dark bar is the footer, which is correctly positioned below the 500px <main> element. The card stretches waaaaay past it - I want the card to be contained between the top of the page and the footer, and have a scrollbar to navigate its contents.

<html lang="en">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 
        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">  
        <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
        <title>Manage List</title>
    </head>

    <body>
        <main style="height: 500px">
            <div class="container-fluid">
                <div class="row">
                    <h1>Dashboard</h1>
                </div>
                <div class="row">
                    <div class="col-7">
                        <div class="card">
                            <div class="card-header">Your Items</div>
                            <div class="card-body overflow-auto">
                                    dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </main>
        <footer class="py-4 bg-dark"></footer>
    </body>
    
    </html>

Related questions I have looked at:
When flexbox items wrap in column mode, container does not grow its width
Prevent flex item from exceeding parent height and make scroll bar work
Why don't flex items shrink past content size?
white-space css property is creating issues with flex
Fitting child into parent
Flex item is not shrinking smaller than its content

I have tried min-height: 0 everywhere, flex-shrink: 1, flex-grow: 0, and other suggestions from the above questions. Really at a loss for what to do next short of pinning the height of every single element down the hierarchy with height: 100% to make sure it doesn't grow past <main>...

Klaycon
  • 10,599
  • 18
  • 35

3 Answers3

1

You have to work your way down the stack, applying d-flex, h-100, and flex-column as you go to get things to fit within their parent container.

<link href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script><script src="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/js/bootstrap.bundle.min.js"></script>

<main style="height: 500px">
    <div class="container-fluid h-100 d-flex flex-column">
        <div class="row">
            <h1>Dashboard</h1>
        </div>
        <div class="row d-flex overflow-hidden">
            <div class="col-7 h-100">
                <div class="card d-flex flex-column h-100">
                    <div class="card-header">Your Items</div>
                    <div class="card-body overflow-auto">
                            dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>
                    </div>
                </div>
            </div>
        </div>
    </div>
</main>
<footer class="py-4 bg-dark"></footer>
Rich DeBourke
  • 2,873
  • 2
  • 15
  • 17
  • This seems effectively identical to my proposed and unwanted solution of pinning everything down the hierarchy (there's more than what's in this example) with `h-100`. It works, but it seems excessive... if this is just the way to do it though then there's nothing else to it. – Klaycon Mar 19 '21 at 17:25
1

The key is to set height or max-height on .card-body.
Below, I calculate the height of <main> and the .card-body based on the viewport.

<html lang="en">

<head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
  <title>Manage List</title>
  <style>
    main {
      padding-bottom: 1em;
      /* viewport height minus footer height  */
      height: calc(100vh - 48px);
    }
    
    main .card .card-body {
      /* viewport height minus footer height minus height of preceeding elements minus main padding-bottom */
      height: calc(100vh - 48px - 7em - 1em);
    }
  </style>
</head>

<body>
  <main style="">
    <div class="container-fluid">
      <div class="row">
        <h1>Dashboard</h1>
      </div>
      <div class="row">
        <div class="col-7">
          <div class="card">
            <div class="card-header">Your Items</div>
            <div class="card-body overflow-auto">
              dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>
            </div>
          </div>
        </div>
      </div>
    </div>
  </main>
  <footer class="py-4 bg-dark"></footer>
</body>

</html>
Arleigh Hix
  • 9,990
  • 1
  • 14
  • 31
  • I thought about this, but this means I'll have to figure out how to calculate the height for each card... which seems like a somewhat inelegant solution. Thank you for your answer. – Klaycon Mar 19 '21 at 17:23
  • I'd usually want solutions to problems like these to be generic, so I can apply them to all problems of this type going forward. Manually calculating the height for the card in this situation means in the future if I have more complex layouts or just two cards on top of each other for example, I'd have to figure out how to calculate it for each. It's a working solution but inelegant. – Klaycon Mar 19 '21 at 18:12
1

You need to make the container h-100 d-flex flex-column, and then h-100 on column and card. Use overflow-hidden on the row so its height is contained by the container.

<main style="height: 500px">
    <div class="container-fluid h-100 d-flex flex-column">
        <div class="row">
            <h1>Dashboard</h1>
        </div>
        <div class="row overflow-hidden">
            <div class="col-7 h-100">
                <div class="card h-100">
                    <div class="card-header">Your Items</div>
                    <div class="card-body overflow-auto"> dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>dsfg<br>
                    </div>
                </div>
            </div>
        </div>
    </div>
</main>
<footer class="py-4 bg-dark"></footer>

Demo

Carol Skelly
  • 351,302
  • 90
  • 710
  • 624