Home > Back-end >  CSS layout with header (fixed), body split in menu (scrollable) and content (scrollable), footer (fi
CSS layout with header (fixed), body split in menu (scrollable) and content (scrollable), footer (fi

Time:08-09

I feel like that question has been asked a few times already but I haven't been able to find an answer to that specific use case.

Here's what I want:

enter image description here

I think the closest post/answer I've been able to find is this one.

I understand and am able to repro it without any issue, see stackblitz live demo.

But as soon as I try to split the main panel into 2 different panels with a left menu and the content, I get a scrollbar on the right and the footer is being pushed right below. I have to scroll to see the footer whereas I only want to be able to scroll in both the left menu and the content but always want to see the header and footer.

Here's my attempt on stackblitz as a minimal repro to show the issue.

About the code:

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

.wrapper {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
}

.body {
  flex: 1;
  width: 100%;
  height: 100%;
  display: flex;
}

.body .menu {
  height: 100%;
  display: flex;
  overflow: auto;
}

.body .content {
  flex: 1;
  overflow: auto;
}
<div >
  <div >header</div>

  <div >
    <div >
      <ul>
        <!-- duplicate this as many times as needed to verify scrolling behavior -->
        <li>Menu Item</li>
      </ul>
    </div>
    <div >
      <ul>
        <!-- duplicate this as many times as needed to verify scrolling behavior -->
        <li>Content Item</li>
      </ul>
    </div>
  </div>

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

Thanks for any help.

CodePudding user response:

If you can fix the width of your left column then you can use absolute positioning on your middle divs to get the overflow you want:

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

.wrapper {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
}

.body {
  flex-grow: 1;
  width: 100%;
  display: flex;
}

.body .menu {
  width: 200px;
}

.body .content {
  flex: 1;
}

.scroll-holder {
  position: relative;
}

.scroll {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  overflow-y: auto;
}

.test {
   height: 1000px;
}
<div >
  <div >header</div>

  <div >
    <div >
      <div >
        <ul>
          <!-- duplicate this as many times as needed to verify scrolling behavior -->
          <li >Menu Item</li>
          <li>Menu Item</li>
        </ul>
      </div>
    </div>

    <div >
      <div >
        <ul>
          <!-- duplicate this as many times as needed to verify scrolling behavior -->
          <li >Content Item</li>
          <li>Content Item</li>
        </ul>
      </div>
    </div>
  </div>

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

With a fluid left column:

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

.wrapper {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
}

.body {
  flex-grow: 1;
  width: 100%;
  position: relative;
}

.body .content {
  flex: 1;
}

.absolute-flex {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: flex;
}

.scroll {
  max-height: 100%;
  overflow: auto;
}

.test {
  height: 1000px;
}
<div >
  <div >header</div>

  <div >
    <div >
      <div >
        <ul>
          <!-- duplicate this as many times as needed to verify scrolling behavior -->
          <li >Menu Item</li>
          <li>Menu Item</li>
        </ul>
      </div>

      <div >
        <ul>
          <!-- duplicate this as many times as needed to verify scrolling behavior -->
          <li >Content Item</li>
          <li>Content Item</li>
        </ul>
      </div>
    </div>
  </div>

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

CodePudding user response:

The height and position attributes are the main things you should play around with.

    html,
    body {
      display: block;
      width: 100%;
      height: 100%;
      max-height: 100vh;
      margin: 0;
      padding: 0;
    }

    .wrapper {
      width: 100%;
      height: 80%;
      display: flex;
      flex-direction: column;
    }

    .body {
      flex: 1;
      width: 100%;
      height: 100%;
      display: flex;
    }

    .body .menu {
      height: 100%;
      display: flex;
      overflow: auto;
    }

    .body .content {
      max-height: 100%;
      flex: 50%;
      justify-content: space-around;
      overflow: auto;
    }


   
 <div >
      <div >header</div>

      <div >
        <div >
          <ul>
            <!-- duplicate this as many times as needed to verify scrolling behavior -->
            <li>Menu Item</li>
            <li>Menu Item</li>
            <li>Menu Item</li>
            <li>Menu Item</li>
            <li>Menu Item</li>
            <li>Menu Item</li>
            <li>Menu Item</li>
            <li>Menu Item</li>
            <li>Menu Item</li>
            <li>Menu Item</li>
            <li>Menu Item</li>
            <li>Menu Item</li>
            <li>Menu Item</li>
            <li>Menu Item</li>
            <li>Menu Item</li>
            <li>Menu Item</li>
            <li>Menu Item</li>
            <li>Menu Item</li>
          </ul>
        </div>
        <div >
          <ul>
            <!-- duplicate this as many times as needed to verify scrolling behavior -->
            <li>Content Item</li>
            <li>Content Item</li>
            <li>Content Item</li>
            <li>Content Item</li>
            <li>Content Item</li>
            <li>Content Item</li>
            <li>Content Item</li>
            <li>Content Item</li>
            <li>Content Item</li>
            <li>Content Item</li>
            <li>Content Item</li>
            <li>Content Item</li>
            <li>Content Item</li>
            <li>Content Item</li>
            <li>Content Item</li>
            <li>Content Item</li>
            <li>Content Item</li>
            <li>Content Item</li>
            <li>Content Item</li>
          </ul>
        </div>
      </div>

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

you might still need to play around to get the result you want.

CodePudding user response:

I think this demo should solve the issue. stackblitz-demo

The trick is to hide the overflow on the body, but only make it to auto on the div you want to scroll in. Then you have to define the height you want that div to be and you should be able to scroll when an overflow occurs. :)

  • Related