skip to Main Content

I’m working on a responsive layout using Bootstrap 5.3 that includes a NavBar, SideBar, ContentPanel, and StatusBar. The app should be always 100% view-height and view-width and contain all information without getting page scrollbars!

The ContentPanel contains an element on the top, a table with dynamic values, and an element at the bottom. I want the table to be as tall as possible without pushing the element below it and the StatusBar outside the viewport!

When I have only a few rows it looks good, here an example:

This is the layout I am aiming for. The ContentPanel should take up as much vertical and horizontal space as possible until without adding page scrollbars.

My problems arises when the table get’s many rows: the table pushes the element below and the StatusBar out of the viewport and the whole page get’s a vertical scrollbar! Here an example:

Too many rows push the Status Bar and the other element out of the viewport.

When the table’s content exceeds the ContentPanel’s size, I want a scrollbar to appear within the table inside the ContentPanel, so you can scroll through the table rows without loosing sight of the StatusBar. The table should take up the remaining height of the ContentPanel after the other elements have been rendered.

So far, I was able to make this work only when I set a maximum height on the table, however then it becomes not as responsive, see here:

[Vertical scrollbar does work when maximum height set, however, it is then not responsive and does not take up as much space as it should. 3

Can somebody help me out? Here my StackBlitz example: https://stackblitz.com/edit/jyee1m?file=index.html

2

Answers


  1. You can achieve this if you set a fixed height to the status bar, which I guess will not vary in contact as much as the content panel. Then you add max-height: calc(100vh - 27px); to the content wrapper and Bootstrap class overflow-auto to the scrollable table so that the scrollbar appears inside the table and not for the whole page. Also, use d-flex flex-column on the content wrapper.

    See the snippet below.

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="utf-8" />
      <meta name="viewport" content="width=device-width, initial-scale=1" />
      <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" />
      <link href="https://getbootstrap.com/docs/5.3/assets/css/docs.css" rel="stylesheet" />
      <title>Bootstrap Example</title>
      <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
      <style>
        .status {
          height: 25px;
        }
        
        .content {
          max-height: calc(100vh - 27px);
        }
      </style>
    </head>
    
    <body class="m-0 p-0 border-0 bd-example bd-example-flex">
      <div class="vh-100 d-flex flex-column">
        <div class="d-flex flex-grow-1">
          <nav class="border p-2">NavBar</nav>
          <aside class="border p-2">SideBar</aside>
          <div class="border p-2 flex-grow-1 content d-flex flex-column">
            ContentPanel
    
            <div class="above-table">Element above table</div>
            <div class="scrollable-table overflow-auto">
              <table class="table" class="table-responsive">
                <thead>
                  <tr>
                    <th scope="col">#</th>
                    <th scope="col">First Name</th>
                    <th scope="col">Last Name</th>
                    <th scope="col">Username</th>
                  </tr>
                </thead>
                <tbody>
                  <tr>
                    <th scope="row">1</th>
                    <td>Mark</td>
                    <td>Otto</td>
                    <td>@mdo</td>
                  </tr>
                  <tr>
                    <th scope="row">2</th>
                    <td>Jacob</td>
                    <td>Thornton</td>
                    <td>@fat</td>
                  </tr>
                  <tr>
                    <th scope="row">3</th>
                    <td>Jacob</td>
                    <td>Thornton</td>
                    <td>@fat</td>
                  </tr>
                  <tr>
                    <th scope="row">4</th>
                    <td>Jacob</td>
                    <td>Thornton</td>
                    <td>@fat</td>
                  </tr>
                  <tr>
                    <th scope="row">5</th>
                    <td>Jacob</td>
                    <td>Thornton</td>
                    <td>@fat</td>
                  </tr>
                  <tr>
                    <th scope="row">6</th>
                    <td>Jacob</td>
                    <td>Thornton</td>
                    <td>@fat</td>
                  </tr>
                  <tr>
                    <th scope="row">7</th>
                    <td>Jacob</td>
                    <td>Thornton</td>
                    <td>@fat</td>
                  </tr>
                  <tr>
                    <th scope="row">8</th>
                    <td>Jacob</td>
                    <td>Thornton</td>
                    <td>@fat</td>
                  </tr>
                  <tr>
                    <th scope="row">9</th>
                    <td>Jacob</td>
                    <td>Thornton</td>
                    <td>@fat</td>
                  </tr>
                  <tr>
                    <th scope="row">10</th>
                    <td>Jacob</td>
                    <td>Thornton</td>
                    <td>@fat</td>
                  </tr>
                  <tr>
                    <th scope="row">11</th>
                    <td>Jacob</td>
                    <td>Thornton</td>
                    <td>@fat</td>
                  </tr>
                  <tr>
                    <th scope="row">12</th>
                    <td>Jacob</td>
                    <td>Thornton</td>
                    <td>@fat</td>
                  </tr>
                  <tr>
                    <th scope="row">13</th>
                    <td>Jacob</td>
                    <td>Thornton</td>
                    <td>@fat</td>
                  </tr>
                  <tr>
                    <th scope="row">14</th>
                    <td>Jacob</td>
                    <td>Thornton</td>
                    <td>@fat</td>
                  </tr>
                  <tr>
                    <th scope="row">15</th>
                    <td>Jacob</td>
                    <td>Thornton</td>
                    <td>@fat</td>
                  </tr>
                  <tr>
                    <th scope="row">16</th>
                    <td>Jacob</td>
                    <td>Thornton</td>
                    <td>@fat</td>
                  </tr>
                  <tr>
                    <th scope="row">17</th>
                    <td>Jacob</td>
                    <td>Thornton</td>
                    <td>@fat</td>
                  </tr>
                  <tr>
                    <th scope="row">18</th>
                    <td>Jacob</td>
                    <td>Thornton</td>
                    <td>@fat</td>
                  </tr>
                  <tr>
                    <th scope="row">19</th>
                    <td>Jacob</td>
                    <td>Thornton</td>
                    <td>@fat</td>
                  </tr>
                  <tr>
                    <th scope="row">20</th>
                    <td>Larry</td>
                    <td>The Bird</td>
                    <td>@twitter</td>
                  </tr>
                  <tr>
                    <th scope="row">20</th>
                    <td>Larry</td>
                    <td>The Bird</td>
                    <td>@twitter</td>
                  </tr>
                  <tr>
                    <th scope="row">20</th>
                    <td>Larry</td>
                    <td>The Bird</td>
                    <td>@twitter</td>
                  </tr>
                  <tr>
                    <th scope="row">20</th>
                    <td>Larry</td>
                    <td>The Bird</td>
                    <td>@twitter</td>
                  </tr>
                  <tr>
                    <th scope="row">20</th>
                    <td>Larry</td>
                    <td>The Bird</td>
                    <td>@twitter</td>
                  </tr>
                  <tr>
                    <th scope="row">20</th>
                    <td>Larry</td>
                    <td>The Bird</td>
                    <td>@twitter</td>
                  </tr>
                  <tr>
                    <th scope="row">20</th>
                    <td>Larry</td>
                    <td>The Bird</td>
                    <td>@twitter</td>
                  </tr>
                  <tr>
                    <th scope="row">20</th>
                    <td>Larry</td>
                    <td>The Bird</td>
                    <td>@twitter</td>
                  </tr>
                  <tr>
                    <th scope="row">20</th>
                    <td>Larry</td>
                    <td>The Bird</td>
                    <td>@twitter</td>
                  </tr>
                  <tr>
                    <th scope="row">20</th>
                    <td>Larry</td>
                    <td>The Bird</td>
                    <td>@twitter</td>
                  </tr>
                  <tr>
                    <th scope="row">20</th>
                    <td>Larry</td>
                    <td>The Bird</td>
                    <td>@twitter</td>
                  </tr>
                  <tr>
                    <th scope="row">20</th>
                    <td>Larry</td>
                    <td>The Bird</td>
                    <td>@twitter</td>
                  </tr>
                </tbody>
              </table>
            </div>
            <div class="below-table">Element below table</div>
          </div>
        </div>
        <div class="border status">StatusBar</div>
      </div>
    </body>
    
    </html>
    Login or Signup to reply.
  2. Apply height: 100vh to the <div> element that wraps the whole webpage via the vh-100 class. With its vertical flex layout and this class, this can be used to limit the sizing of elements within.

    We apply min-height: 0 to various inner elements to override the min-height: min-content that would otherwise apply by default due to the vertical flex layouts.

    We apply max-height: 100% via mh-100, and invoke a vertical flex layout to give the ContentPanel <div> a height constraint of its parent element, so that the inner .scrollable-table element will have a constraint to shrink to.

    .scrollable-table {
      overflow-y: auto;
    }
    
    .min-h-0 {
      min-height: 0;
    }
    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <link
          href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"
          rel="stylesheet"
        />
        <link
          href="https://getbootstrap.com/docs/5.3/assets/css/docs.css"
          rel="stylesheet"
        />
        <title>Bootstrap Example</title>
        <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
      </head>
      <body class="m-0 p-0 border-0 bd-example bd-example-flex">
        <div class="vh-100 d-flex flex-column vh-100">
          <div class="d-flex flex-grow-1 min-h-0">
            <nav class="border p-2">NavBar</nav>
            <aside class="border p-2">SideBar</aside>
            <div class="border p-2 flex-grow-1 d-flex flex-column min-h-0 mh-100">
              ContentPanel
    
              <div>Element above table</div>
              <div class="scrollable-table min-h-0">
                <table class="table" class="table-responsive">
                  <thead>
                    <tr>
                      <th scope="col">#</th>
                      <th scope="col">First Name</th>
                      <th scope="col">Last Name</th>
                      <th scope="col">Username</th>
                    </tr>
                  </thead>
                  <tbody>
                    <tr>
                      <th scope="row">1</th>
                      <td>Mark</td>
                      <td>Otto</td>
                      <td>@mdo</td>
                    </tr>
                    <tr>
                      <th scope="row">2</th>
                      <td>Jacob</td>
                      <td>Thornton</td>
                      <td>@fat</td>
                    </tr>
                    <tr>
                      <th scope="row">3</th>
                      <td>Jacob</td>
                      <td>Thornton</td>
                      <td>@fat</td>
                    </tr>
                    <tr>
                      <th scope="row">4</th>
                      <td>Jacob</td>
                      <td>Thornton</td>
                      <td>@fat</td>
                    </tr>
                    <tr>
                      <th scope="row">5</th>
                      <td>Jacob</td>
                      <td>Thornton</td>
                      <td>@fat</td>
                    </tr>
                    <tr>
                      <th scope="row">6</th>
                      <td>Jacob</td>
                      <td>Thornton</td>
                      <td>@fat</td>
                    </tr>
                    <tr>
                      <th scope="row">7</th>
                      <td>Jacob</td>
                      <td>Thornton</td>
                      <td>@fat</td>
                    </tr>
                    <tr>
                      <th scope="row">8</th>
                      <td>Jacob</td>
                      <td>Thornton</td>
                      <td>@fat</td>
                    </tr>
                    <tr>
                      <th scope="row">9</th>
                      <td>Jacob</td>
                      <td>Thornton</td>
                      <td>@fat</td>
                    </tr>
                    <tr>
                      <th scope="row">10</th>
                      <td>Jacob</td>
                      <td>Thornton</td>
                      <td>@fat</td>
                    </tr>
                    <tr>
                      <th scope="row">11</th>
                      <td>Jacob</td>
                      <td>Thornton</td>
                      <td>@fat</td>
                    </tr>
                    <tr>
                      <th scope="row">12</th>
                      <td>Jacob</td>
                      <td>Thornton</td>
                      <td>@fat</td>
                    </tr>
                    <tr>
                      <th scope="row">13</th>
                      <td>Jacob</td>
                      <td>Thornton</td>
                      <td>@fat</td>
                    </tr>
                    <tr>
                      <th scope="row">14</th>
                      <td>Jacob</td>
                      <td>Thornton</td>
                      <td>@fat</td>
                    </tr>
                    <tr>
                      <th scope="row">15</th>
                      <td>Jacob</td>
                      <td>Thornton</td>
                      <td>@fat</td>
                    </tr>
                    <tr>
                      <th scope="row">16</th>
                      <td>Jacob</td>
                      <td>Thornton</td>
                      <td>@fat</td>
                    </tr>
                    <tr>
                      <th scope="row">17</th>
                      <td>Jacob</td>
                      <td>Thornton</td>
                      <td>@fat</td>
                    </tr>
                    <tr>
                      <th scope="row">18</th>
                      <td>Jacob</td>
                      <td>Thornton</td>
                      <td>@fat</td>
                    </tr>
                    <tr>
                      <th scope="row">19</th>
                      <td>Jacob</td>
                      <td>Thornton</td>
                      <td>@fat</td>
                    </tr>
                    <tr>
                      <th scope="row">20</th>
                      <td>Larry</td>
                      <td>The Bird</td>
                      <td>@twitter</td>
                    </tr>
                  </tbody>
                </table>
              </div>
              <div>Element below table</div>
            </div>
          </div>
          <div class="border">StatusBar</div>
        </div>
      </body>
    </html>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search