Home > database >  Nested full-height CSS flexbox columns, scrolling behavior
Nested full-height CSS flexbox columns, scrolling behavior

Time:12-31

I'm trying to create a full-height layout where only the bottom "part" of the layout scrolls. That is, a couple fixed title bars and then the whole area below scrolls.

Could be done with tables or absolute positioning, but seems like flexbox is the modern answer. And it seems to work fine with a flat column flexbox with three divs and flex: 1; overflow: auto in the last div. But not when flexboxes are nested. When I use nested flexboxes, I always get a scrollbar on the whole page, never a scrollbar in the main content area.

This flat flexbox layout works as intended:

outer
    b1
    b2
    b3

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

.outer {
  background: white;
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
}

.b1 {
  background: lightblue;
}

.b2 {
  background: pink;
}

.b3 {
  flex: 1;
  background: green;
  overflow: auto;
}
<div class='outer'>
  <div class='b1'>
    b1
  </div>
  <div class='b2'>
    b2
  </div>
  <div class='b3'>
    b3<br/> b3
    <br/> b3
    <br/> b3
    <br/> b3
    <br/> b3
    <br/> b3
    <br/> b3
    <br/> b3
    <br/> b3
    <br/> b3
    <br/>
  </div>
</div>

This nested structure doesn't work as intended:

outer
    a1
    a2
        b1
        b2

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

.outer {
  background: white;
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
}

.a1 {
  background: lightblue;
}

.a2 {
  flex: 1;
  background: green;
  display: flex;
  flex-direction: column;
}

.b1 {
  background: pink;
}

.b2 {
  flex: 1;
  background: yellow;
  overflow: auto;
}
<div class='outer'>
  <div class='a1'>
    a1
  </div>
  <div class='a2'>
    <div class='b1'>
      b1
    </div>
    <div class='b2'>
      b2<br/> b2
      <br/> b2
      <br/> b2
      <br/> b2
      <br/> b2
      <br/> b2
      <br/> b2
      <br/> b2
      <br/> b2
      <br/> b2
      <br/>
    </div>
  </div>
</div>

CodePudding user response:

I have tried to add a fixed position to your example above and ended up with the result below. Only some css code was edited.

...

.a1 {
  background: lightblue;
  position : fixed;
  width: 100%;
}

...

.b1 {
  background: pink;
  position: fixed;
  width: 100%;
  transform: translate(0, 100%);
}

See the full code at codepen.io here.

CodePudding user response:

Here is an example using grid. Flexbox likes to grow to fit its children so when you use it to explicitly set heights and make things scroll you're fighting that layout tool, grid works better in this case.

I removed some width declarations and the padding declaration on your root and body element which all do absolutely nothing!

html,
body {
  margin: 0;
  height: 100%;
  font-size: 1em;
}

* {
  box-sizing: border-box;
}

.outer {
  height: 100%;
  display: grid;
  grid-template-rows: 2em 1fr;
  background: white;
  overflow: auto;
}

.a1 {
  background: lightblue;
}

.a2 {
  height: 100%;
  display: grid;
  grid-template-rows: 2em 1fr;
  background: green;
  overflow: auto;
}

.b1 {
  background: pink;
}

.b2 {
  background: yellow;
  overflow: auto;
}
<div class='outer'>
  <div class='a1'>
    a1
  </div>
  <div class='a2'>
    <div class='b1'>
      b1
    </div>
    <div class='b2'>
      b2<br/> b2
      <br/> b2
      <br/> b2
      <br/> b2
      <br/> b2
      <br/> b2
      <br/> b2
      <br/> b2
      <br/> b2
      <br/> b2
      <br/>
    </div>
  </div>
</div>

  • Related