AdamAL AdamAL - 20 days ago 9
CSS Question

How to add scroll to child of flex item?

With a flex container with a fixed height, I can make a flex item scrollable by setting

overflow: auto
, like so:



page {
display: flex;
flex-flow: row wrap;
height: 200px;
}
left-panel {
flex: 1;
display: block;
background: lightblue;
}
//main {flex: 5; display: block;}
header {
background: turquoise;
display: block
}
//main-content-wrapper {flex: 4; display:flex; flex-direction: column}
right-panel {
flex: 1;
overflow: auto;
}
content-panel {
background: pink;
display: block;
}
content {
height: 1000px;
display: block;
}

<page>
<left-panel>left-panel
<br/>(static)</left-panel>
<right-panel>
<header>
header
<br/>(static)
</header>
<content-panel>
<content>
content
<br/>(scrolls)
</content>
</content-panel>
</right-panel>
</page>





fiddle

But I would like to make a child of the flex item scroll instead.

I would think that setting
height: 100%
on the flex item and
overflow: auto
on the child element I want to scroll would work, but it does not:



page {
display: flex;
flex-flow: row wrap;
height: 200px;
}
left-panel {
flex: 1;
display: block;
background: lightblue;
}
//main {flex: 5; display: block;}
header {
background: turquoise;
display: block
}
//main-content-wrapper {flex: 4; display:flex; flex-direction: column}
right-panel {
flex: 1;
height: 100%;
}
content-panel {
background: pink;
display: block;
overflow: auto;
}
content {
height: 1000px;
display: block;
}

<page>
<left-panel>left-panel
<br/>(static)</left-panel>
<right-panel>
<header>
header
<br/>(static)
</header>
<content-panel>
<content>content
<br/>(scrolls)</content>
</content-panel>
</right-panel>
</page>





fiddle

How can I make this work?

And why doesn't the second fiddle work?

Added OP comments:


  • I can see there are several related questions, but the ones I found are either not directly applicable, or mention workarounds to bugs that may have been fixed since.

  • I would like to avoid using explicit height calculations to reduce coupling of components.

  • I could convert the right-panel into a nested flexbox with
    flex-direction: column
    , but I was hoping to avoid that.

  • In case a flat structure (like in the second fiddle) is not possible without an explicit height calculation, it would be nice with an explanation of why. Could it be considered a bug with flexbox or am I misunderstanding something fundamental about css?


Answer

If you're applying overflow: auto to an element so it can launch a vertical scrollbar, then also give it a height limitation.

In this case, you just need to add height: 100% to the element you want to make scrollable.

content-panel {
  background: pink;
  display: block;
  overflow: auto;
  height: 100%; /* NEW */
}

Of course, you'll need to adjust the actual percentage value to subtract the height of the header. Maybe something like this:

height: calc(100% - 80px)

OR, perhaps a better approach (and consistent with your added comments rejecting fixed heights), just make right-panel a column-direction flex container:

page {
  display: flex;
  flex-flow: row wrap;
  height: 200px;
}
left-panel {
  flex: 1;
  display: block;
  background: lightblue;
}
header {
  background: turquoise;
  display: block
}
right-panel {
  flex: 1;
  height: 100%;
  display: flex;          /* NEW */
  flex-direction: column; /* NEW */
}
content-panel {
  background: pink;
  overflow: auto;
}
content {
  height: 1000px;
  display: block;
}
<page>
  <left-panel>left-panel
    <br/> (static)</left-panel>
  <right-panel>
    <header>
      header
      <br/>(static)
    </header>
    <content-panel>
      <content>content
        <br/>(scrolls)</content>
    </content-panel>
  </right-panel>
</page>


EDIT (based on revised question)

With regard to the overflow property:

The overflow property specifies whether to clip content, render scrollbars or just display content when it overflows its block level container.

In order for the overflow property to have an effect, the block level container must either have a bounding height (height or max-height) or have white-space set to nowrap.

https://developer.mozilla.org/en-US/docs/Web/CSS/overflow

Comments