如何在嵌套的 flexbox 上下文中控制后代框的高度?

How to control the height of descendant box within a nested flexbox context?

.main {
  height: 100px;
  width: 100px;
  border: 1px solid;
  background: green;
}
.columns {
  display: flex;
}

.columns.vertical {
  flex-direction: column;
  flex-wrap: nowrap;
}

.box22 {
  overflow: auto;
}
.box1 {
  background: red;
}
.box2 {
  background: orange;
  border: 1px blue solid;
}
.box222 {
  background: white;
  border: 1px blue solid;
}
<md-content class="md-padding">
  <div class="main columns vertical">
    <nav class="box1">nav</nav>
    <div class="box columns vertical">
      <div class="b">asdasd</div>
      <div class="box2 columns vertical">
        <div class="box21 columns">
          box21
        </div>
        <div class="box22 columns">
          <div class="box221">box221</div>
          <div class="box222">
            <p>a</p>
            <p>a</p>
          </div>
        </div>
      </div>
    </div>
  </div>
</md-content>

我手动设置了最外层框的高度 main 并且还设置了 box22overflow:auto,但是 box22 拉长了 main 框并且没有滚动条出现。

我想要的是在最外面的盒子设置高度,嵌套的内部盒子可以自动控制它的高度,所以所有的盒子都适合。如何解决这类问题,我应该为所有后代框设置高度吗?

我在box(level1)box2(level2)box22(level3)测试了设置overflow :auto,只有box(level1)可以自动控制它的高度并显示滚动条它的高度重叠。

我想要的如下图,然而,要实现这个,我需要手动指定box22的父框。换句话说,如果我想让一个 flex contaner 可以滚动,我至少得设置它的 father box 的高度,这是完全不能接受的。

.main {
  height: 100px;
  width: 100px;
  border: 1px solid;
  background: green;
}
.columns {
  display: flex;
}

.columns.vertical {
  flex-direction: column;
  flex-wrap: nowrap;
}
.box22 {
  overflow: auto;
}
.box1 {
  background: red;
}
.box2 {
  height:64px;
  background: orange;
  border: 1px blue solid;
}
.box21 {
  background: yellow;
}
.box222 {
  background: white;
  border: 1px blue solid;
  margin-top: auto;
}
<md-content class="md-padding">
  <div class="main columns vertical">
    <nav class="box1">nav</nav>
    <div class="box columns vertical">
      <div class="b">asdasd</div>
      <div class="box2 columns vertical">
        <div class="box21 columns">
          box21
        </div>
        <div class="box22 columns">
          <div class="box221">box221</div>
          <div class="box222">
            <p>a</p>
            <p>a</p>
            <p>a</p>
          </div>
        </div>
      </div>
    </div>
  </div>
</md-content>

考虑在 main 上使用 max-height 而不是 height...如果你从 flexbox 开始...最好在整个链中保持 display: flex

.top {
  position: static;
  height: 200px;
  width: 200px;
  max-height: 200px;
  max-width: 200px;
  overflow: auto;
}

.flexcol {
  width: 100%;
  display: flex;
  flex-direction: column;
  padding: 0;
}

.mynav {
  display: flex;
  flex-direction: row;
  flex-grow: 1;
  background-color: blue;
}

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

.box2 {
  display: flex;
  flex-direction: column;
  flex-grow: 1;
  background-color: green;
}

.box3 {
  display: flex;
  flex-grow: 1;
  background-color: yellow;
}

.box221 {
  min-height: 50px;
  background-color: pink;
  width: 100%;
}

.box222 {
  min-height: 50px;
  background-color: grey;
  width: 100%;
}

.darklink {
  color: white;
}
<div class="top">
  <div class="flexcol">
    <nav class="mynav">
      <a class="darklink" href="#" target="_">Link1</a>
      <a class="darklink" href="#" target="_">Link2</a>
      <a class="darklink" href="#" target="_">Link3</a>
   </nav>
    <div class="box1">
      <p>para</p>
    </div>
    <div class="box2">
      <div class="box221">
        <p>para</p>
        <p>para</p>
      </div>
      <div class="box222">
        <p>para</p>
        <p>para</p>
        <p>para</p>
      </div>
    </div>
    <div class="box3">
      <p>para</p>
    </div>
  </div>
</div>

好吧,如您所述,父容器需要声明高度才能生成滚动条。

这是有道理的,因为如果没有固定长度,就无法触发溢出条件。

使用灵活的长度(例如,height: auto),容器将收缩和扩展以容纳内容,永远不会触发溢出,因此永远不会生成滚动条。

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.

这就是你的障碍。以下是解决方法(知道您不能设置更多高度):

  1. 为浏览器提供触发溢出所需的内容: 设置一个很小的 ​​(1px) 高度。
  2. 你得到你想要的全高:使用flex-grow消耗剩余的space.

所以像这样...

height: 1px;
flex-grow: 1;

但效率更高:

flex: 1 0 1px; /* fg, fs, fb */

将此添加到您的代码中:

.main  .columns.vertical {
  flex: 1 0 1px;
}
.box22 {
  flex: 1 0 1px;
}

.main {
  height: 100px;
  width: 100px;
  border: 1px solid;
  background: green;
}

/* NEW */
.main .columns.vertical {
  flex: 1 0 1px;
}

/* ADJUSTMENT */
.box22 {
  flex: 1 0 1px;
  overflow: auto;
}

.columns {
  display: flex;
}

.columns.vertical {
  flex-direction: column;
  flex-wrap: nowrap;
}

.box22 {
  flex: 1 0 1px;
  overflow: auto;
}

.box1 {
  background: red;
}

.box2 {
  background: orange;
  border: 1px blue solid;
}

.box222 {
  background: white;
  border: 1px blue solid;
}
<md-content class="md-padding">
  <div class="main columns vertical">
    <nav class="box1">nav</nav>
    <div class="box columns vertical">
      <div class="b">asdasd</div>
      <div class="box2 columns vertical">
        <div class="box21 columns">box21</div>
        <div class="box22 columns">
          <div class="box221">box221</div>
          <div class="box222">
            <p>a</p>
            <p>a</p>
          </div>
        </div>
      </div>
    </div>
  </div>
</md-content>