Set vertical scrollbar on flex children, not whole page

我的梦境 提交于 2021-01-28 05:09:22

问题


I am trying to make a page which consists of a header, a left nav and some content.

I would like the left nav and the content to reach up to the bottom of the viewport, so that no scroll bar appears for the whole page.

However both the left nav and the content can be very large, so I would like each of them to have a scroll for overflow-y.

I have tried using blocks/floats but didn't manage to achieve my intended result. I saw that flex has the flex-grow which seemed to offer a solution, however I haven't managed to make it work.

In the fiddle below I have attempted to have a column flexbox for the header and remaining site, and a row flexbox for the left nav and content, however these grow beyond the height of the viewport.

https://jsfiddle.net/ph8qnfky/4/

body {
    height: 100%;
    margin: 0;
}

.viewportDiv {
  display: flex;
  flex-flow: column;
  height: 100%;
}

.header{
  background-color: yellow;
  height: 100px;
  min-height: 100px;
}

.remainingDiv{
  background-color: red;
  flex-grow: 1;
}

.mainSite {
  display: flex;
  flex-direction: row;
  flex-grow: 1;

  /* max-height: 100px; */

}

.leftNav{
  background-color: green;
  width: 200px;
  overflow-y: scroll;
}

.content {
  background-color: grey;
  overflow-y: scroll;
}
<div class="viewportDiv">
  <div class="header">Site header</div>
  <div class="remainingDiv">
   <div class="mainSite">


    <div class="leftNav">
      <div>item</div>
      <div>item</div>
      <div>item</div>
      <div>item</div>
      <div>item</div>
      <div>item</div>
      <div>item</div>
      <div>item</div>
      <div>item</div>
      <div>item</div>
      <div>item</div>
      <div>item</div>
      <div>item</div>
      <div>item</div>
      <div>item</div>
      <div>item</div>
      <div>item</div>
      <div>item</div>
      <div>item</div>
      <div>item</div>
      <div>item</div>
      <div>item</div>
      <div>item</div>
      <div>item</div>
      <div>item</div>

    </div>
    <div class="content">
      Lorem ipsum dolor sit amet, <br/> consectetur adipiscing elit. <br/>Aliquam vel ullamcorper ligula. Vestibulum nibh arcu, mollis in commodo ut, tristique sed sapien. Cras elementum facilisis consequat. Suspendisse eleifend gravida arcu, a rhoncus mi placerat at. <br/>Cras et vestibulum nulla, at vestibulum arcu. Pellentesque at aliquam turpis. Integer consequat tristique diam scelerisque consequat. <br/>Nullam mattis condimentum diam, sed tincidunt lacus iaculis a. Sed eu ex arcu. <br/>Nullam libero enim, venenatis quis vehicula id, fermentum vitae sapien. Praesent vehicula est id orci rhoncus, <br/>dignissim sodales risus commodo.
      Lorem ipsum dolor sit amet, <br/> consectetur adipiscing elit. <br/>Aliquam vel ullamcorper ligula. Vestibulum nibh arcu, mollis in commodo ut, tristique sed sapien. Cras elementum facilisis consequat. Suspendisse eleifend gravida arcu, a rhoncus mi placerat at. <br/>Cras et vestibulum nulla, at vestibulum arcu. Pellentesque at aliquam turpis. Integer consequat tristique diam scelerisque consequat. <br/>Nullam mattis condimentum diam, sed tincidunt lacus iaculis a. Sed eu ex arcu. <br/>Nullam libero enim, venenatis quis vehicula id, fermentum vitae sapien. Praesent vehicula est id orci rhoncus, <br/>dignissim sodales risus commodo.
            Lorem ipsum dolor sit amet, <br/> consectetur adipiscing elit. <br/>Aliquam vel ullamcorper ligula. Vestibulum nibh arcu, mollis in commodo ut, tristique sed sapien. Cras elementum facilisis consequat. Suspendisse eleifend gravida arcu, a rhoncus mi placerat at. <br/>Cras et vestibulum nulla, at vestibulum arcu. Pellentesque at aliquam turpis. Integer consequat tristique diam scelerisque consequat. <br/>Nullam mattis condimentum diam, sed tincidunt lacus iaculis a. Sed eu ex arcu. <br/>Nullam libero enim, venenatis quis vehicula id, fermentum vitae sapien. Praesent vehicula est id orci rhoncus, <br/>dignissim sodales risus commodo.
                  Lorem ipsum dolor sit amet, <br/> consectetur adipiscing elit. <br/>Aliquam vel ullamcorper ligula. Vestibulum nibh arcu, mollis in commodo ut, tristique sed sapien. Cras elementum facilisis consequat. Suspendisse eleifend gravida arcu, a rhoncus mi placerat at. <br/>Cras et vestibulum nulla, at vestibulum arcu. Pellentesque at aliquam turpis. Integer consequat tristique diam scelerisque consequat. <br/>Nullam mattis condimentum diam, sed tincidunt lacus iaculis a. Sed eu ex arcu. <br/>Nullam libero enim, venenatis quis vehicula id, fermentum vitae sapien. Praesent vehicula est id orci rhoncus, <br/>dignissim sodales risus commodo.
    </div>
   </div>
  </div>
</div>

I would like to achieve both leftNav and content to cut off at viewport end and have their scroll bars enabled.

I am trying to solve this with flex as it seemed to be a good fit, but if there is a non-flex solution involving only css I would not have a problem using it.

Best regards


回答1:


For the overflow property to work reliably across browsers it needs to have a fixed height or width. Flex properties don't always trigger an overflow condition. flex-grow almost never works because it doesn't set a length, it simply consumes free space, and overflow doesn't pay attention to that.

From MDN:

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

In this case, because the layout occupies the height of the viewport (height: 100vh), and there are only two siblings, with one (the .header) having a fixed height of 100px, the solution is relatively simple.

Set the other sibling (.remainingDiv) to height: calc(100vh - 100px), then give the overflowing children height: 100%. This will generate the scrollbars you want.

.viewportDiv {
  display: flex;
  flex-flow: column;
  height: 100vh;
}

.header {
  background-color: yellow;
  flex: 0 0 100px;  /* more efficient than original rules (disables flex-shrink) */
}

.remainingDiv {
  background-color: red;
  flex: 0 0 calc(100vh - 100px); /* occupy remaining height */
  height: calc(100vh - 100px); /* fallback, as some browsers may not accept
                                  flex-basis in this case */
  display: flex;  /* make children occupy full height */
  min-height: 0;  /* patch for Firefox */
}

.mainSite {
  display: flex;
  height: 100%; /* take height of parent */
}

.leftNav {
  background-color: green;
  flex: 0 0 200px; /* more efficient than original rule (disables flex-shrink) */
  overflow-y: scroll;
}

.content {
  background-color: grey;
  overflow-y: scroll;
}

body {
  margin: 0;
}
<div class="viewportDiv">
  <div class="header">Site header</div>
  <div class="remainingDiv">
    <div class="mainSite">
      <div class="leftNav">
        <div>item</div>
        <div>item</div>
        <div>item</div>
        <div>item</div>
        <div>item</div>
        <div>item</div>
        <div>item</div>
        <div>item</div>
        <div>item</div>
        <div>item</div>
        <div>item</div>
        <div>item</div>
        <div>item</div>
        <div>item</div>
        <div>item</div>
        <div>item</div>
        <div>item</div>
        <div>item</div>
        <div>item</div>
        <div>item</div>
        <div>item</div>
        <div>item</div>
        <div>item</div>
        <div>item</div>
        <div>item</div>
      </div>
      <div class="content">
        Lorem ipsum dolor sit amet, <br/> consectetur adipiscing elit. <br/>Aliquam vel ullamcorper ligula. Vestibulum nibh arcu, mollis in commodo ut, tristique sed sapien. Cras elementum facilisis consequat. Suspendisse eleifend gravida arcu, a rhoncus
        mi placerat at. <br/>Cras et vestibulum nulla, at vestibulum arcu. Pellentesque at aliquam turpis. Integer consequat tristique diam scelerisque consequat. <br/>Nullam mattis condimentum diam, sed tincidunt lacus iaculis a. Sed eu ex arcu. <br/>Nullam
        libero enim, venenatis quis vehicula id, fermentum vitae sapien. Praesent vehicula est id orci rhoncus, <br/>dignissim sodales risus commodo. Lorem ipsum dolor sit amet, <br/> consectetur adipiscing elit. <br/>Aliquam vel ullamcorper ligula. Vestibulum
        nibh arcu, mollis in commodo ut, tristique sed sapien. Cras elementum facilisis consequat. Suspendisse eleifend gravida arcu, a rhoncus mi placerat at. <br/>Cras et vestibulum nulla, at vestibulum arcu. Pellentesque at aliquam turpis. Integer
        consequat tristique diam scelerisque consequat. <br/>Nullam mattis condimentum diam, sed tincidunt lacus iaculis a. Sed eu ex arcu. <br/>Nullam libero enim, venenatis quis vehicula id, fermentum vitae sapien. Praesent vehicula est id orci rhoncus,
        <br/>dignissim sodales risus commodo. Lorem ipsum dolor sit amet, <br/> consectetur adipiscing elit. <br/>Aliquam vel ullamcorper ligula. Vestibulum nibh arcu, mollis in commodo ut, tristique sed sapien. Cras elementum facilisis consequat. Suspendisse
        eleifend gravida arcu, a rhoncus mi placerat at. <br/>Cras et vestibulum nulla, at vestibulum arcu. Pellentesque at aliquam turpis. Integer consequat tristique diam scelerisque consequat. <br/>Nullam mattis condimentum diam, sed tincidunt lacus
        iaculis a. Sed eu ex arcu. <br/>Nullam libero enim, venenatis quis vehicula id, fermentum vitae sapien. Praesent vehicula est id orci rhoncus, <br/>dignissim sodales risus commodo. Lorem ipsum dolor sit amet, <br/> consectetur adipiscing elit.
        <br/>Aliquam vel ullamcorper ligula. Vestibulum nibh arcu, mollis in commodo ut, tristique sed sapien. Cras elementum facilisis consequat. Suspendisse eleifend gravida arcu, a rhoncus mi placerat at. <br/>Cras et vestibulum nulla, at vestibulum
        arcu. Pellentesque at aliquam turpis. Integer consequat tristique diam scelerisque consequat. <br/>Nullam mattis condimentum diam, sed tincidunt lacus iaculis a. Sed eu ex arcu. <br/>Nullam libero enim, venenatis quis vehicula id, fermentum vitae
        sapien. Praesent vehicula est id orci rhoncus, <br/>dignissim sodales risus commodo.
      </div>
    </div>
  </div>
</div>

revised fiddle




回答2:


Add max-height: 100vh; to .mainSite, so it would be something like this:

.mainSite {
  display: flex;
  flex-direction: row;
  flex-grow: 1;
  max-height: 100vh;
}

CSS Units



来源:https://stackoverflow.com/questions/57747410/set-vertical-scrollbar-on-flex-children-not-whole-page

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!