akc42 akc42 - 25 days ago 6
HTML Question

How can I arrange for a horizontal scroll bar on overflow with flexbox items?

I am trying to arrange a layout in which I have a right hand side bar and to the left of it in a main content area I have a list of items of fixed width arranged horizontally.

There are various numbers of these and when they get more than will fit in to the space allowed I want a horizontal scroll bar to appear.

As it happens, each item in this list also contains a header and a list of sub items which could overflow vertically. This too needs a scroll bar.

The following jsbin shows what I am attempting, but fails on the horizontal arrangement. Unfortunately the sidebar gets squashed to a small width before scroll bars appear. Also, it's clearly the whole viewport which gets the horizontal scroll bar as my main heading starts scrolling too.

https://jsbin.com/qametad/edit?html,css,output

How can I get it so the area with class "s" (see jsbin) is the one that horizontally scrolls? (It doesn't have to be "s", I had tried to get "ic" scrolling initially but failed at that so added "s" to try to separate out the flexing and the scrolling).



body {
fullbleed height: 100vh;
}
.h {
display: flex;
flex-direction: row;
justify-content: center;
height: 30px;
}
.m {
display: flex;
flex-direction: row;
height: calc(100vh - 50px);
border: 1px solid green;
}
.ic {
display: flex;
flex: 1;
}
.s {
display: flex;
flex-direction: row;
border: 1px solid red;
width: 100%;
overflow-x: auto;
}
.i {
display: flex;
flex-direction: column;
width: 150px;
border: 1px solid rebeccapurple;
margin: 1px
}
.ih {
height: 50px;
self-align: center;
border: 1px solid orange;
}
.il {
margin: 1px;
border: 1px solid black;
overflow-y: auto;
}
.li {
height: 60px;
margin: 3px;
border: 1px solid lawngreen;
}
.sb {
display: flex;
flex-direction: column;
justify-content: center;
margin: 2px;
border: 1px solid blue;
}

<header class="h">My Heading</header>
<section class="m">
<div class="ic">
<div class="s">
<div class="i">
<header class="ih">Item Header</header>
<section class="il">
<div class="li">A</div>
<div class="li">B</div>
<div class="li">C</div>
</section>
</div>
<div class="i">
<header class="ih">Item Header</header>
<section class="il">
<div class="li">A</div>
<div class="li">B</div>
<div class="li">C</div>
<div class="li">C</div>
<div class="li">C</div>
<div class="li">C</div>
<div class="li">C</div>
<div class="li">C</div>
<div class="li">C</div>
</section>
</div>
<div class="i">
<header class="ih">Item Header</header>
<section class="il">
<div class="li">A</div>
<div class="li">B</div>
<div class="li">C</div>
</section>
</div>
<div class="i">
<header class="ih">Item Header</header>
<section class="il">
<div class="li">A</div>
<div class="li">B</div>
<div class="li">C</div>
</section>
</div>
<div class="i">
<header class="ih">Item Header</header>
<section class="il">
<div class="li">A</div>
<div class="li">B</div>
<div class="li">C</div>
</section>
</div>
</div>
</div>
<section class="sb">
<div class="sbc">Some Content</div>
</section </section>




Answer

An initial setting of a flex container is flex-shrink: 1 (source).

Hence, your .i elements (the columns) are allowed to shrink when the container gets smaller.

To disable shrinking use flex-shrink: 0.

.i {
  display: flex;
  flex-direction: column;
  width: 150px;
  border: 1px solid rebeccapurple;
  margin: 1px
  flex-shrink: 0; /* NEW */
}

Now the horizontal scrollbar works on your .ic container.

.ic {
  display: flex;
  flex: 1;
  overflow-x: auto;
}

revised demo

More details here: What are the differences between flex-basis and width?

Comments