Let’s first briefly discuss what we want to achieve. I am using
Bootstrap v5.0
grid layout in my HTML
pages. I have a long dynamic data list sitting in a div
,
and so this div
must have a vertical scrollbar, users can select a row at a time from this list
to move to a second list. They can also remove a row from this second list, and the just removed
row will be moved back to the first list.
As the second list grows, the vertical scrollbar will eventually appear. And on the first list, the vertical scrollbar could disappear. It goes without saying, if enough rows get removed from the second list, the vertical scrollbar would disappear also.
The above behaviour happens naturally, all we have to do is setting the height and
vertical scrolling on the two div
s.
The two lists also have a header or a label row, each. And this’s where the issue is: I want the scrollbar to always sit under the header row, and the data columns must always align with the respective header columns — both when the list has the vertical scrollbar and without. The below screen capture, from the demo page, shows this behaviour:
Originally, I had JavaScript
to recalculate the columns’ width
in response to when a vertical scrollbar appears and disappears — I had around
45 (forty five) lines of JavaScript
, and still, I could not get
it to work correctly at all times. After some searching, I came to this
scrollbar-gutter
CSS
property.
It is so beautiful, and easy to use… Please run the following demo to see this
CSS
property in action:
🚀 Demo URL — https://behai-nguyen.github.io/demo/063/css-vertical-scrollbar.html
It’s a self-contained page, you can copy it to your localhost and play around with
it. For example, try removing scrollbar-gutter: stable;
from:
.vertical-scrollable {
overflow-y: auto;
overflow-x: hidden;
scrollbar-gutter: stable;
}
to see how it affects the layout.
Please note that, I have vertical-scrollable
on both lists’
header rows:
<div class="row py-2 border-bottom vertical-scrollable">
...
This feels strange, since the header rows do not have a scrollbar. There is a reason for it. The documentation scrollbar-gutter states:
The scrollbar-gutter CSS property allows authors to reserve space for the scrollbar, preventing unwanted layout changes as the content grows while also avoiding unnecessary visuals when scrolling isn’t needed.
An element’s scrollbar gutter is the space between the inner border edge and the outer padding edge, where the browser may display a scrollbar. If no scrollbar is present, the gutter will be painted as an extension of the padding.
So, basically, I am just “reserving” vertical scrollbar space on the header rows, so that header columns are pushed to the left by the same amount as the data columns — making them always aligned.
The div
containers for the two lists should be self-explanatory:
<div class="col-6 vertical-scrollable data-list-height selector-available-data"></div>
<div class="col-6 vertical-scrollable data-list-height selector-selected-data" data-render-target="true"></div>
This demo page is actually a simplified version of pages from a project I have been working. An example of a page:
I do realise that Bootstrap v5.0 handles vertical scrollbar quite well, if we accept the default behaviour: the scrollbar actually comes up beside the header row. I do not like this look, this is the only reason why I went through all this trouble. It feels satisfying nailing this issue at last though 😂.
I hope you find this information useful. Thank you for reading. And stay safe as always.
✿✿✿
Feature image sources: