Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bootstrap 4 full-height card with independent scrollable columns

I want to make a card that will function as a chat body and therefore take the full height of the screen as nothing else will be displayed besides the chat body and I want it to occupy all the space on the screen. In the card, I have two columns need to be both independently scrollable. So I don't want the website to be scrollable, but the two columns inside the card. First column is for the actual chat, the second one is for a list of chatting users.

While I got it to work with setting hardcoded max-height values by pixels, I cannot seem to get it working with the automatic full screen height.

What happens is the card is being rendered as full height, but the content overflows the card despite having an overflow-y: auto, when setting the overflow to scroll it basically makes an scrollbar the exact height of the content.

Code:

html, body
{
  height: 100vh;
}
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" rel="stylesheet"/>

<div class="container h-100">
  <div class="card h-100">
    <div class="card-header">
      100% Height card
    </div>
    <div class="card-body">
      <div class="row">
        <div class="col-10">
          <div style="overflow-y: scroll;" class="mh-100">
          	Independent scrollable column<br>
           	Text<br>
            Text<br>
            Text<br>
            Text<br>
            Text<br>
            Text<br>
            Text<br>
            Text<br>
            Text<br>
            Text<br>
            Text<br>
            Text<br>
            Text<br>
            Text<br>
            Text<br>
            Text<br>
            Text<br>
            Text<br>
            Text<br>
            Text<br>
            Text<br>
            Text<br>
          </div>
        </div>
        <div class="col-2">
          <div stlye="overflow-y: auto" class="mh-100">
            Independent scrollable column #2
            Text<br>
            Text<br>
            Text<br>
            Text<br>
            Text<br>
            Text<br>
            Text<br>
            Text<br>
            Text<br>
            Text<br>
            Text<br>
            Text<br>
            Text<br>
            Text<br>
            Text<br>
            Text<br>
            Text<br>
            Text<br>
            Text<br>
            Text<br>
            Text<br>
          </div>
        </div>
    </div>
  </div>
</div>

As for now I went for calculating the max-height in jQuery as it's fairly simple and allows me to put any content I desire without worrying about changing the height percentages:

$(document).ready(function()
{
    calculateHeight();
    $(window).resize(function() { calculateHeight() });
});

function calculateHeight()
{
    let wnHeight = $(window).height();
    let boxHeight = $("#messagesBox").height();
    let cardHeight = $("#messagesCard").outerHeight();
    let cardPos = $("#messagesCard").offset();
    // calculate the offset to the bottom, this is how much we need to expand (or shrink)
    let offset = boxHeight + (wnHeight - (cardHeight + cardPos.top));
    if(offset < 480) // this just prevents the card from getting too small
        offset = 480;
    $("#messagesBox").css('max-height', `${offset}px`);
}
like image 743
hazelnutek Avatar asked Oct 16 '22 11:10

hazelnutek


1 Answers

I have made an example of how to approach this using FLEX and SIZING utilities from Bootstrap 4. First, with CSS, we divide the total view-port height between the card-header and card-body (15% to header and 85% to body). Second, we use w-* classes in replacement of col-* for the body-width division, with d-flex class applied to the body. Third, and just to keep html markup simple, we fill the containers from JQuery. Hope this helps you.

$(document).ready(function()
{
    // Fill the message and friend containers.

    for (var i = 0; i < 30; i++)
    {
        $("#msgWrap").append("<div class='text-primary'>Message " + i + "</div>");
        $("#friendWrap").append("<div class='text-danger'>Friend " + i + "</div>");
    }
});
html, body {
    height: 100vh;
}

.card-header {
    max-height: 15vh;
}

.card-body {
    max-height: 85vh;
}
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>

<div class="container-fluid">
  <div class="card">

    <div class="card-header d-flex align-items-center text-white bg-dark">
      <span class="mx-auto">100% Height card</span>
    </div>

    <div class="card-body d-flex">
      <div id="msgCol" class="d-flex flex-column w-75">
         <div id="msgWrap" class="w-100" style="overflow-y:scroll"></div>
         <input class="w-100" type="text" placeholder="Write a new message"/>
      </div>

      <div id="friendCol" class="d-flex flex-column w-25">
        <div id="friendWrap" class="w-100" style="overflow-y:scroll"></div>
        <div class="w-100 border border-primary text-center text-bold">
          FOOTER
        </div>
      </div>
    </div>

  </div>
</div>
like image 180
Shidersz Avatar answered Nov 11 '22 22:11

Shidersz