Search code examples
htmlcsscss-tables

Three-row modal with fixed with header, bottom row, and scrollable middle row


I am trying to create a modal with a top, middle and bottom. The top is always fixed height.

The bottom must be "glued" to the bottom and may vary some. All content and elements inside it must build from the bottom. So if there is one line of text, the bottom will be the height of that line. If there are 3 or 4 lines of text, the bottom will push up as needed.

The middle needs to fill up all that is left, and if the content overflow-y's it must show the scroll bar and not interfere with the top or bottom row.

How would I do this? I'm finding when I try overflow-y: auto it's not working, presumably because there is not height, but instead it pushes the table outside the bounds of the #wrap div.

Here is a CodePen: https://codepen.io/sfullman/pen/XGZoJb

    body{
      font-family: Arial;
    }
    .table{
      display: table;
      height: 100%;
      width: 100%;
    }
    .row{
      display: table-row;
    }
    .cell{
      display: table-cell;
      width: 75%;
    }
    #top{
      background-color: burlywood;
      height: 41px;
    }
    #middle .cell{
      overflow-y: scroll;
    }
    #bottom{
      height: 15px; /* make this height less than expected height, table row/cell behavior will successfully exceed it an push content up */
      border-top: 1px solid darkred;
      background-color: rgba(0,0,0,.15);
    }
    #wrap{
      /* this div is designed to be a dialog/modal and will normally be abs. positioned */
      border: 1px solid darkred;
      width: 425px;
      height: 300px;
      position: absolute;
      top: 20px;
      left: 20px;
    }
    <div id="wrap">
      <div id="innerTable" class="table">
      <div id="top" class="row">
        <div class="cell">
        top
        </div>
      </div>
      <div id="middle" class="row">
        <div class="cell">
          middle<br>
          middle<br>
          middle<br>
          middle<br>
          middle<br>
          middle<br>
          middle<br>
          middle<br>
          middle<br>
          middle<br>
          middle<br>
          middle<br>
        </div>
      </div>
      <div id="bottom" class="row">
        <div class="cell">
        bottom<br>
        bottom<br>
        bottom<br>
        </div>
      </div>
    </div>
    </div>


Solution

  • After searching on the web, I found something on JS fiddle which I then modified to create the solution here

    Here is the HTML:

    <div id="body">
         <div id="head">
           <!-- if your have content larger than declared height here, it will simply roll under the bottom with no scrolling -->
            <p>Fixed size without scrollbar 1</p>
            <p>Fixed size without scrollbar 2</p>
            <p>Fixed size without scrollbar 3</p>
            <p>Fixed size without scrollbar 4</p>
        </div> 
        <div id="content">
            <!--
            add or remove these to see scrool/non-scroll behavior
            -->
            <p>Dynamic size with scrollbar</p>
            <p>Dynamic size with scrollbar</p>
            <p>Dynamic size with scrollbar</p>
            <p>Dynamic size with scrollbar</p>
            <p>Dynamic size with scrollbar</p>
            <p>Dynamic size with scrollbar</p>
            <!--
            <p>Dynamic size with scrollbar</p>
            <p>Dynamic size with scrollbar</p>
            <p>Dynamic size with scrollbar</p>
            <p>Dynamic size with scrollbar</p>
            <p>Dynamic size with scrollbar</p>
            <p>Dynamic size with scrollbar</p>
            <p>Dynamic size with scrollbar</p>
            <p>Dynamic size with scrollbar</p>
            <p>Dynamic size with scrollbar</p>
            <p>Dynamic size with scrollbar</p>
            <p>Dynamic size with scrollbar</p>
            <p>Dynamic size with scrollbar</p>
            <p>Dynamic size with scrollbar</p>
            <p>Dynamic size with scrollbar</p>
            <p>Dynamic size with scrollbar</p>
            <p>Dynamic size with scrollbar</p>
            <p>Dynamic size with scrollbar</p>
            -->
        </div>
        <div id="foot">
          <!-- this content will build from the bottom, pushing the top wall up. #content's bottom will adjust up accordingly -->
            <p>Dynamic size without scrollbar 1</p>
            <p>Dynamic size without scrollbar 2</p>
            <p>Dynamic size without scrollbar 3</p>
        </div> 
    </div>
    

    And the CSS:

    #body {
        position: absolute;
        top: 15px;
        left: 15px;
        height: 300px;
        width: 500px;
        outline: black dashed 1px;
        display: flex;
        flex-direction: column;
    }
    
    #head {
        /*border: blue solid 1px;*/
        background-color: rgba(0,0,255,0.25);
        height: 50px;
        flex-shrink: 0;
    }
    #content{
        /*border: red solid 1px;*/
        background-color: palegoldenrod;
        overflow-y: auto;
        height: 100%;
    }
    
    #foot {
        /*border: green solid 1px;*/
        background-color: whitesmoke;
        flex-shrink: 0;
    }