John Mellor
John Mellor

Reputation: 2513

Make two columns separately scrollable and the height of the remaining length of the viewport

I've got a JS Fiddle working of exactly what I would like: http://jsfiddle.net/j7ay4qd8/5/

It comprises of two columns which are separately scrollable and different sections of the left column can be easily scrolled to via javascript without affecting the right column or the rest of the page.

However the only way i've got this working for this example is to hardcode the height using the px's of the two nav's.

height:calc(100vh - 90px);

Of course this may not work on different browsers, devices and resolutions.

And it will break if any elements are added or the size of those navs changes.

What I really want is for the #form to automatically resize to fill whatever is left of the viewport.

With my current example, if I added another element such as an alert the #content and #sidebar would be longer than the viewport and i'd get jumpy scroll as the whole page scrolls after the #content div has scrolled.

Example with alert and jumpy scroll: http://jsfiddle.net/c4k9u0mr/

I've found this jsfiddle which seems to explain what I want using flexbox: http://jsfiddle.net/7yLFL/

However my attempts at doing this with flexbox haven't worked either. The only way that I can get the #content and #guidelines to be separately scrollable is if I give them a fixed height and i'm back to square one of how to make those divs 100% of the container div.

Here's my failed attempt using flexbox (it has a fixed height of 100px in this example): http://jsfiddle.net/jh6d5ztq/

Is it possible to get the first and second JS Fiddle's working without defining a fixed height using px?

Upvotes: 3

Views: 1467

Answers (1)

mahan
mahan

Reputation: 15035

  1. All the parents of the elements that takes the remaining height of the viewport need to have a 100% heights. In bootstrap, use h-100.

  2. The closest parent of these elements needs to be flex and must have flex-direction: column. In bootstrap, use d-flex and flex-column. Some classes such as row is already flex so do not use d-flex.

  3. Use flex-grow-1 for the element that takes the remaining height. Again, some classes such as col have flex-grow:1.

Bootstrap flex classes

html,
body {
  height: 100%;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css" rel="stylesheet" />
<div class="d-flex flex-column h-100">
  <div class="py-3 bg-danger">

  </div>
  <div class="py-3 bg-danger">

  </div>
  <div class="flex-grow-1 bg-primary">

  </div>
</div>


Bootstrap grid

html,
body {
  height: 100%;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css" rel="stylesheet"/>
<div class="fluid-container h-100">
  <div class="row flex-column h-100">
    <div class="col-auto py-3 bg-danger">

    </div>
    <div class="col-auto py-3 bg-success">

    </div>
    <div class="col bg-primary">

    </div>
  </div>
</div>


Now, div.col / div.flex-grow-1 takes the remaining height of the viewport. However, if their contents' height is more than that of the viewport, they won't do: their height is the same as the height of their content. If you want to make it scrollable, use overflow: auto. I guess, bootstrap-4, does not have a class for none of the overflow properties. So you should use custom css.

https://codepen.io/anon/pen/JwWpgQ


As a side note, if you want to have the footer at the bottom, use these methods but interchange the col with col-auto


If you want to have more than one element scrollable separately, use overflow-auto and h-100 for those elements.

html,
body {
  height: 100%;
}

.overflow-auto {
  overflow: auto;
}

.h-200vh {
  height: 200vh;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css" rel="stylesheet" />
<div class="fluid-container h-100">
  <div class="row flex-column h-100">
    <div class="col-auto py-3 bg-danger">
    </div>
    <div class="col-auto py-3 bg-success">
    </div>
    <div class="col bg-dark d-flex">
      <div class="w-50 h-100 overflow-auto">
        <div class="bg-danger h-200vh"></div>
      </div>
      <div class="w-50 overflow-auto h-100">
        <div class="bg-primary h-200vh"></div>
      </div>
    </div>
  </div>
</div>

https://codepen.io/anon/pen/QzpQRO


Conclusion:

Use bootstrap grid as you would normally do but use flex-column on row and col for the element that takes all the remaining height of the viewport. If you want to make it scrollable, use a custom css to apply overflow:auto.


Comment if you have any question, and I will answer. I have solved your problems, but I wont post it because I think it is best that you try first.

Update

This is my solution. https://codepen.io/anon/pen/Jwrzwm

Upvotes: 3

Related Questions