1

I want to make a website with a list using bootstrap + css's flexbox, where the item list should have a height up to the screen's bottom not overflowing it.

I was able to get a working solution like this:

html,
body {
  width: 100%;
  height: 100%;
  overflow: hidden;
  margin: 0;
}

body {
  background-color: black;
}

.wrapper .content-wrapper .content {
  flex: 1 1 1px;
}

.wrapper .content-wrapper .content {
  display: flex;
  flex-direction: column;
}

.wrapper .content-wrapper {
  width: 100%;
}

.wrapper {
  display: flex;
  height: 100%;
}

.side {
  background-color: blue;
  display: flex;
  flex-direction: column;
  width: 224px;
}

.content-wrapper {
  display: flex;
  flex-direction: column;
}

.topbar {
  height: 100px;
  background-color: aqua;
}

.main {
  flex: 1 1 1px;
  background-color: pink;
  overflow-y: scroll;
}

.item {
  background-color: white;
  border-style: solid;
  height: 200px;
}
<html>

<head>
  <link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.4.1/css/bootstrap.min.css" rel="stylesheet" />
</head>

<body>
  <div class="wrapper">
    <div class="side"></div>
    <div class="content-wrapper">
      <div class="content">
        <div class="topbar"></div>
        <div class="main">
          <div class="item">item</div>
          <div class="item">item</div>
          <div class="item">item</div>
          <div class="item">item</div>
          <div class="item">item</div>
          <div class="item">item</div>
          <div class="item">item</div>
        </div>
      </div>
    </div>
  </div>
</body>

</html>

With the help from this link: Prevent flex item from exceeding parent height and make scroll bar work

As you can see the scroll bar's bottom arrow is at the end of the screen. (Expected behaviour)

However, when I try to expand my main div into 2 more columns (using bootstrap + flex):

html,
body {
  width: 100%;
  height: 100%;
  overflow: hidden;
  margin: 0;
}

body {
  background-color: black;
}

.wrapper .content-wrapper .content {
  flex: 1 1 1px;
}

.wrapper .content-wrapper .content {
  display: flex;
  flex-direction: column;
}

.wrapper .content-wrapper {
  width: 100%;
}

.wrapper {
  display: flex;
  height: 100%;
}

.side {
  background-color: blue;
  display: flex;
  flex-direction: column;
  width: 224px;
}

.content-wrapper {
  display: flex;
  flex-direction: column;
}

.topbar {
  height: 100px;
  background-color: aqua;
}

.main {
  flex: 1 1 1px;
  background-color: pink;
  display: flex;
}

.header {
  background-color: yellow;
  overflow-y: scroll;
  height: 100%;
}

.details {
  background-color: crimson;
}

.item {
  background-color: white;
  border-style: solid;
  height: 200px;
}
<html>

<head>
  <link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.4.1/css/bootstrap.min.css" rel="stylesheet" />
</head>

<body>
  <div class="wrapper">
    <div class="side"></div>
    <div class="content-wrapper">
      <div class="content">
        <div class="topbar"></div>
        <div class="main">
          <div class="header col-lg-4">
            <div class="item">item</div>
            <div class="item">item</div>
            <div class="item">item</div>
            <div class="item">item</div>
            <div class="item">item</div>
            <div class="item">item</div>
            <div class="item">item</div>
          </div>
          <div class="details col-lg-8"></div>
        </div>
      </div>
    </div>
  </div>
</body>

</html>

Now the item list overflow below the bottom of the screen. (see the bottom arrow of the scrollbar is missing)

Any help would be appreciated.

Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
SG2010
  • 33
  • 2
  • 6

1 Answers1

2

You have a couple of fixed lengths in your code, including:

.side {
  width: 224px;
}

.topbar {
  height: 100px;
}

These hard limits make the solution to overflow problems relatively simple, since the easiest way to trigger a scrollbar is to create an overflow condition, which is best accomplished with a fixed length.

In this case, the .topbar { height: 100px } is the key to the scrollbar on the sibling element.

(Note that you need to disable flex-shrink on these lengths for the values to always be respected.)

Here's a revised version of your code, with various adjustments for greater performance and efficiency.

body {
  margin: 0;
  background-color: black;
}

.wrapper {
  display: flex;
  height: 100vh;
}

.side {
  /* width: 224px; */ /* will not be respected without adding `flex-shrink: 0` */
  flex: 0 0 224px;    /* new; flex-grow, flex-shrink, flex-basis */
  background-color: blue;
  display: flex;
  flex-direction: column;
}

.content-wrapper {
  flex: 1;  /* consume remaining space */
  display: flex;
  flex-direction: column;
}

.wrapper .content-wrapper .content {
  display: flex;
  flex-direction: column;
}

.topbar {
  flex: 0 0 100px;
  /* height: 100px; */
  background-color: aqua;
}

.main {
  height: calc(100vh - 100px); /* new; sets overflow condition */
  background-color: pink;
  display: flex;
}

.header {
  background-color: yellow;
  overflow-y: scroll;
  /* height: 100%; */
}

.details {
  background-color: crimson;
}

.item {
  background-color: white;
  border-style: solid;
  height: 200px;  /* not a flex item, so no need to disable flex-shrink */
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.4.1/css/bootstrap.min.css" rel="stylesheet"/>
<div class="wrapper">
  <div class="side"></div>
  <div class="content-wrapper">
    <div class="content">
      <div class="topbar"></div>
      <div class="main">
        <div class="header col-lg-4">
          <div class="item">item</div>
          <div class="item">item</div>
          <div class="item">item</div>
          <div class="item">item</div>
          <div class="item">item</div>
          <div class="item">item</div>
          <div class="item">item</div>
        </div>
        <div class="details col-lg-8"></div>
      </div>
    </div>
  </div>
</div>

jsFiddle demo

Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
  • Hi Michael_B, Thanks for solving it so quickly. I wonder if there's another way where I don't have to use height: calc(100vh - 100px) but use flex instead? (i.e. consume the rest of the space) – SG2010 Mar 27 '20 at 03:39
  • Try adding `height: 100vh` to `.content`, and `height: 1px; flex-grow: 1` to `main`. https://jsfiddle.net/vLu3rz5t/ – Michael Benjamin Mar 27 '20 at 04:01