Nesting flexbox inside flexbox overflow. How to fix this?

こ雲淡風輕ζ 提交于 2021-01-28 08:03:48

问题


So I was trying to get a header and some content to fit into the screen by having a div #main with height: 100% as a flexbox, just like this:

#main {
    height: 150px; /* Using a fixed height here, otherwise the snippet wouldn't work */
}
.flexbox {
    display: flex;
    flex-direction: column;
}
.header {
    flex: 0 1 auto;
    border: 2px solid #aa0000;
}
.content {
    flex: 1 1 auto;
    border: 2px solid #00aa00;
}
.scrollable {
    overflow-y: scroll;
}
<html>
    <body>
        <div id="main" class="flexbox">
            <div class="header">
                HEADER
            </div>
            <div class="content scrollable">
                CONTENT<br>CONTENT<br>CONTENT<br>CONTENT<br>
                CONTENT<br>CONTENT<br>CONTENT<br>CONTENT<br>
                CONTENT<br>CONTENT<br>CONTENT<br>CONTENT<br>
                CONTENT<br>CONTENT<br>CONTENT<br>CONTENT<br>
            </div>
        </div>
    </body>
</html>

So now if #content overflows the height of #main, #content's scrollbar will take over, and the header stays visible. Works like a charm so far.

My problem is now that I need to nest another combination of header and screen fitting content into the outer content, which I tried to solve with another nested flexbox:

#main {
    height: 150px; /* Using a fixed height here, otherwise the snippet wouldn't work */
}
.flexbox {
    display: flex;
    flex-direction: column;
}
.header {
    flex: 0 1 auto;
    border: 2px solid #aa0000;
}
.content {
    flex: 1 1 auto;
    border: 2px solid #00aa00;
}
.scrollable {
    overflow-y: scroll;
}
<html>
    <body>
        <div id="main" class="flexbox">
            <div class="header">
                HEADER
            </div>
            <div class="content flexbox">
                <div class="header">
                    HEADER
                </div>
                <div class="content scrollable">
                    CONTENT<br>CONTENT<br>CONTENT<br>CONTENT<br>
                    CONTENT<br>CONTENT<br>CONTENT<br>CONTENT<br>
                    CONTENT<br>CONTENT<br>CONTENT<br>CONTENT<br>
                    CONTENT<br>CONTENT<br>CONTENT<br>CONTENT<br>
                </div>
            </div>
        </div>
    </body>
</html>

So basically I want both headers to stay up top now, and have only the inner content box scroll once it overflows. But when it does, the content stretches beyond (?!) #main's height, triggering the browser pages's scrollbar instead of its own one. I suppose the problem may be caused by the outer content box, whose height is only defined by the outer flexbox.

I already had tried a solution where the headers would have absolute positions, but this doesn't quite work out for what I need it. Flexboxes would be just perfect if it wasn't for this problem.

Can anyone help me fix this?


回答1:


What you ask for is already happening in Chrome. Which makes me think you're developing with FF.


As a side-note, I believe that's a mistake, simply because you're developing for less than 15% of your target audience to only fix browser differences for another 65% of your audience. Luckily for you, they both keep tight to standards and differences are quite few these days.
Another reason why you might prefer Chrome over FF as a development tool is that FF has consistently been 6 months behind regarding dev tools for at least 4 years now. Don't get me wrong, I'm not a big Chrome fan and I fully welcome using FF as browsing device of choice. But, as a development tool, it's just not the best available. And they're both free.


Back to your question, adding overflow-y:auto to .flexbox seems to fix it in FF, too:

#main {
    height: 150px; /* Using a fixed height here, otherwise the snippet wouldn't work */
}
.flexbox {
    display: flex;
    flex-direction: column;
    overflow-y: auto;
}
.header {
    flex: 0 1 auto;
    border: 2px solid #aa0000;
}
.content {
    flex: 1 1 auto;
    border: 2px solid #00aa00;
}
.scrollable {
    overflow-y: scroll;
}
<html>
    <body>
        <div id="main" class="flexbox">
            <div class="header">
                HEADER
            </div>
            <div class="content flexbox">
                <div class="header">
                    HEADER
                </div>
                <div class="content scrollable">
                    CONTENT<br>CONTENT<br>CONTENT<br>CONTENT<br>
                    CONTENT<br>CONTENT<br>CONTENT<br>CONTENT<br>
                    CONTENT<br>CONTENT<br>CONTENT<br>CONTENT<br>
                    CONTENT<br>CONTENT<br>CONTENT<br>CONTENT<br>
                </div>
            </div>
        </div>
    </body>
</html>

Note: of course, you'd need to run your code through a prefixer for a wider browser coverage. Mind the "filter" box below it. Set to > 0% for maximum cross-browser compatibility.




回答2:


This issue affects not only Firefox, also Edge and IE11 overflow the parent.

It's caused by the fact that flex item's min-height* defaults to auto, and as such can't be smaller than its content. (Chrome tries to fix this by itself, hence it works on it, though, IMHO, it shouldn't)

* Very well explained here: The Implied Minimum Size of Flex Items

The affected element is the <div class="content flexbox">, which will overflow because if this.

The solution is to change its min-height to 0, and with that will allow it to shrink past content.

For IE11, see notes/sample below.

Stack snippet

#main {
    height: 150px; /* Using a fixed height here, otherwise the snippet wouldn't work */
}
.flexbox {
    display: flex;
    flex-direction: column;
}
.header {
    /*flex: 0 1 auto;                       default, so not needed  */
    border: 2px solid #aa0000;
}
.content {
    flex: 1 1 auto;
    border: 2px solid #00aa00;
    min-height: 0;                      /*  Firefox, Edge  */
}
.scrollable {
    overflow-y: scroll;
}
<div id="main" class="flexbox">
  <div class="header">
    HEADER
  </div>
  <div class="content flexbox">
    <div class="header">
      HEADER
    </div>
    <div class="content scrollable">
      CONTENT<br>CONTENT<br>CONTENT<br>CONTENT<br> CONTENT
      <br>CONTENT<br>CONTENT<br>CONTENT<br> CONTENT
      <br>CONTENT<br>CONTENT<br>CONTENT<br> CONTENT
      <br>CONTENT<br>CONTENT<br>CONTENT<br>
    </div>
  </div>
</div>

As IE11 being a lot buggier, the above isn't enough, and there is 2 ways to fix it:

Using flex: 1 1 0%, which will make IE11 believe there is no content, hence will only grow as big as the available space in its parent.

#main {
    height: 150px; /* Using a fixed height here, otherwise the snippet wouldn't work */
}
.flexbox {
    display: flex;
    flex-direction: column;
}
.header {
    /*flex: 0 1 auto;                       default, so not needed  */
    border: 2px solid #aa0000;
}
.content {
    flex: 1 1 0%;                       /*  IE11, changed from "auto" to "0%" */
    border: 2px solid #00aa00;
    min-height: 0;                      /*  Firefox, Edge  */
}
.scrollable {
    overflow-y: scroll;
}
<div id="main" class="flexbox">
  <div class="header">
    HEADER
  </div>
  <div class="content flexbox">
    <div class="header">
      HEADER
    </div>
    <div class="content scrollable">
      CONTENT<br>CONTENT<br>CONTENT<br>CONTENT<br> CONTENT
      <br>CONTENT<br>CONTENT<br>CONTENT<br> CONTENT
      <br>CONTENT<br>CONTENT<br>CONTENT<br> CONTENT
      <br>CONTENT<br>CONTENT<br>CONTENT<br>
    </div>
  </div>
</div>

Using overflow: hidden (see note at the end)

#main {
    height: 150px; /* Using a fixed height here, otherwise the snippet wouldn't work */
}
.flexbox {
    display: flex;
    flex-direction: column;
}
.header {
    /*flex: 0 1 auto;                       default, so not needed  */
    border: 2px solid #aa0000;
}
.content {
    flex: 1 1 auto;
    border: 2px solid #00aa00;
    /*min-height: 0;                        not needed, as overflow has same effect  */
    overflow: hidden;                   /*  Firefox, Edge, IE11  */
}
.scrollable {
    overflow-y: scroll;
}
<div id="main" class="flexbox">
  <div class="header">
    HEADER
  </div>
  <div class="content flexbox">
    <div class="header">
      HEADER
    </div>
    <div class="content scrollable">
      CONTENT<br>CONTENT<br>CONTENT<br>CONTENT<br> CONTENT
      <br>CONTENT<br>CONTENT<br>CONTENT<br> CONTENT
      <br>CONTENT<br>CONTENT<br>CONTENT<br> CONTENT
      <br>CONTENT<br>CONTENT<br>CONTENT<br>
    </div>
  </div>
</div>

Note, using overflow with a value other than visible (its default), will have the same effect as min-height, where hidden is considered more safe than auto, avoiding future change in behavior to render a scrollbar.




回答3:


You can fix this by using two height: 0 on the main box and the content box.

html,
body {
  height: 100%;
}

.topheader {
  background: orange;
  width: 90%;
}

#container {
  display: flex;
  flex-direction: column;
  height: 100%;
  width: 50%;
  background: red;
}


.subcontainer {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  height: 0;
  width: 90%;
  background: blue;
}

#container header {
  background-color: gray;
}

#container article {
  flex: 1 1 auto;
  overflow-y: auto;
  height: 0;
  opacity: 0.5;

}

#container footer {
  background-color: gray;
}
<section id="container">
  <div class="topheader">
    Top Header
  </div>
  <div class="subcontainer">
    <header id="header">This is a header</header>
    <article id="content">
      This is the content that
      <br />
      With a lot of lines.
      <br />
      With a lot of lines.
      <br />
      This is the content that
      <br />
      With a lot of lines.
      <br />
      <br />
      This is the content that
      <br />
      With a lot of lines.<br />
      With a lot of lines.
      <br />
      This is the content that
      <br />
      With a lot of lines.
      <br />
      <br />
      This is the content that
      <br />
      With a lot of lines<br />
      With a lot of lines.
      <br />
      This is the content that
      <br />
      With a lot of lines.
      <br />
      <br />
      This is the content that
      <br />
      With a lot of lines
      <br />
      <br />
      This is the content that
      <br />
      With a lot of lines.
      <br />
    </article>
    <footer id="footer">This is a footer</footer>
  </div>
</section>


来源:https://stackoverflow.com/questions/48389994/nesting-flexbox-inside-flexbox-overflow-how-to-fix-this

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