【问题标题】:nested flexbox height vs max-height嵌套的弹性盒高度与最大高度
【发布时间】:2019-08-04 03:48:30
【问题描述】:

更新:我在 Chrome 72 上看到了这种奇怪的行为。FireFox 64 没问题!

我遇到了嵌套弹性框的问题。

在下面的 sn-p 中,我向.root.container 添加了一个虚拟 XL 高度,因此当有许多 items 超出可用的最大高度时,结果正是我想要的。

相反,当项目很少时,.root.container 不应延伸到所有可用高度。

换句话说,我希望.root.container 的高度为auto,但我不知道怎么做。
移除它的虚拟高度,在.root.content 而不是.sub.content 上触发溢出。

请帮助我了解 flexbox 在这种特殊情况下的工作原理。

附:小提琴也可用here

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

* {
  box-sizing: border-box;
}

div {
  padding: 10px;
}

.container {
  display: flex;
  flex-direction: column;
}

.content {
  flex: 1;
  max-height: 100%;
  overflow: auto;
}

.root.container {
  background-color: red;
  max-height: 100%;
  height: 999999px; /* i want height to be 'auto' */
}

.sub.container {
  background-color: purple;
  height: 100%;
}

.root.header {
  background-color: lightblue;
}

.sub.header {
  background-color: lightgreen;
}

.root.content {
  background-color: yellow;
}

.sub.content {
  background-color: orange;
}
<div class="root container">
  <div class="root header">header</div>
  <div class="root content">
    <div class="sub container">
      <div class="sub header">menu</div>
      <div class="sub content">
        <ul>
          <li>Item 1</li>
          <li>Item 2</li>
          <li>Item 3</li>
          <li>Item 4</li>
          <li>Item 5</li>
          <li>Item 1</li>
          <li>Item 2</li>
          <li>Item 3</li>
          <li>Item 4</li>
          <li>Item 5</li>
          <li>Item 1</li>
          <li>Item 2</li>
          <li>Item 3</li>
          <li>Item 4</li>
          <li>Item 5</li>
          <li>Item 1</li>
          <li>Item 2</li>
          <li>Item 3</li>
          <li>Item 4</li>
          <li>Item 5</li>
          <li>Item 1</li>
          <li>Item 2</li>
          <li>Item 3</li>
          <li>Item 4</li>
          <li>Item 5</li>
          <li>Item 1</li>
          <li>Item 2</li>
          <li>Item 3</li>
          <li>Item 4</li>
          <li>Item 5</li>
          <li>Item 1</li>
          <li>Item 2</li>
          <li>Item 3</li>
          <li>Item 4</li>
          <li>Item 5</li>
          <li>Item 1</li>
          <li>Item 2</li>
          <li>Item 3</li>
          <li>Item 4</li>
          <li>Item 5</li>
          <li>Item 1</li>
          <li>Item 2</li>
          <li>Item 3</li>
          <li>Item 4</li>
          <li>Item 5</li>
          <li>Item 1</li>
          <li>Item 2</li>
          <li>Item 3</li>
          <li>Item 4</li>
          <li>Item 5</li>
          <li>Item 1</li>
          <li>Item 2</li>
          <li>Item 3</li>
          <li>Item 4</li>
          <li>Item 5</li>
        </ul>
      </div>
    </div>
  </div>
</div>

【问题讨论】:

    标签: html css google-chrome firefox flexbox


    【解决方案1】:

    您的代码在设置大高度时按预期工作,因为max-height:100% in the child element need a reference,如果您删除高度,max-height 将无法自动运行。附带说明一下,即使您删除了max-height,Firefox 也会有相同的输出,因此问题与max-height 无关。 1

    相反,您可以保留级联 flex 容器并依靠默认的拉伸对齐来获得您想要的:

    html, body {
      height: 100%;
      margin: 0;
      padding: 0;
    }
    
    * {
      box-sizing: border-box;
    }
    
    div {
      padding: 10px;
    }
    
    .container {
      display: flex;
      flex-direction: column;
    }
    
    .content {
      flex: 1;
      max-height: 100%;
      overflow: auto;
    }
    
    .root.container {
      background-color: red;
      max-height: 100%;
    }
    
    .sub.container {
      background-color: purple;
      width:100%; /*added this*/
    }
    
    .root.header {
      background-color: lightblue;
    }
    
    .sub.header {
      background-color: lightgreen;
    }
    
    .root.content {
      background-color: yellow;
      display:flex; /*added this*/
    }
    
    .sub.content {
      background-color: orange;
    }
    <div class="root container">
      <div class="root header">header</div>
      <div class="root content">
        <div class="sub container">
          <div class="sub header">menu</div>
          <div class="sub content">
            <ul>
              <li>Item 1</li>
              <li>Item 2</li>
              <li>Item 3</li>
              <li>Item 4</li>
              <li>Item 5</li>
              <li>Item 1</li>
              <li>Item 2</li>
              <li>Item 3</li>
              <li>Item 4</li>
              <li>Item 5</li>
              <li>Item 1</li>
              <li>Item 2</li>
              <li>Item 3</li>
              <li>Item 4</li>
              <li>Item 5</li>
              <li>Item 1</li>
              <li>Item 2</li>
              <li>Item 3</li>
              <li>Item 4</li>
              <li>Item 5</li>
              <li>Item 1</li>
              <li>Item 2</li>
              <li>Item 3</li>
              <li>Item 4</li>
              <li>Item 5</li>
              <li>Item 1</li>
              <li>Item 2</li>
              <li>Item 3</li>
              <li>Item 4</li>
              <li>Item 5</li>
              <li>Item 1</li>
              <li>Item 2</li>
              <li>Item 3</li>
              <li>Item 4</li>
              <li>Item 5</li>
              <li>Item 1</li>
              <li>Item 2</li>
              <li>Item 3</li>
              <li>Item 4</li>
              <li>Item 5</li>
              <li>Item 1</li>
              <li>Item 2</li>
              <li>Item 3</li>
              <li>Item 4</li>
              <li>Item 5</li>
              <li>Item 1</li>
              <li>Item 2</li>
              <li>Item 3</li>
              <li>Item 4</li>
              <li>Item 5</li>
              <li>Item 1</li>
              <li>Item 2</li>
              <li>Item 3</li>
              <li>Item 4</li>
              <li>Item 5</li>
            </ul>
          </div>
        </div>
      </div>
    </div>

    为了更好地查看问题,让我们删除一些属性并仅保留会触发不同行为的所需属性:

    html, body {
      height: 100%;
      margin: 0;
      padding: 0;
    }
    
    * {
      box-sizing: border-box;
    }
    
    div {
      padding: 10px;
    }
    
    .container {
      display: flex;
      flex-direction: column;
    }
    
    .content {
      flex: 1;
      overflow: auto;
    }
    
    .root.container {
      background-color: red;
      max-height: 100%;
    }
    
    .sub.container {
      background-color: purple;
      height: 100%;
    }
    
    
    .root.header {
      background-color: lightblue;
    }
    
    .sub.header {
      background-color: lightgreen;
    }
    
    .root.content {
      background-color: yellow;
    }
    
    .sub.content {
      background-color: orange;
    }
    <div class="root container">
      <div class="root header">header</div>
      <div class="root content">
        <div class="sub container">
          <div class="sub header">menu</div>
          <div class="sub content">
            <ul>
              <li>Item 1</li>
              <li>Item 2</li>
              <li>Item 3</li>
              <li>Item 4</li>
              <li>Item 5</li>
              <li>Item 1</li>
              <li>Item 2</li>
              <li>Item 3</li>
              <li>Item 4</li>
              <li>Item 5</li>
              <li>Item 1</li>
              <li>Item 2</li>
              <li>Item 3</li>
              <li>Item 4</li>
              <li>Item 5</li>
              <li>Item 1</li>
              <li>Item 2</li>
              <li>Item 3</li>
              <li>Item 4</li>
              <li>Item 5</li>
              <li>Item 1</li>
              <li>Item 2</li>
              <li>Item 3</li>
              <li>Item 4</li>
              <li>Item 5</li>
              <li>Item 1</li>
              <li>Item 2</li>
              <li>Item 3</li>
              <li>Item 4</li>
              <li>Item 5</li>
              <li>Item 1</li>
              <li>Item 2</li>
              <li>Item 3</li>
              <li>Item 4</li>
              <li>Item 5</li>
              <li>Item 1</li>
              <li>Item 2</li>
              <li>Item 3</li>
              <li>Item 4</li>
              <li>Item 5</li>
              <li>Item 1</li>
              <li>Item 2</li>
              <li>Item 3</li>
              <li>Item 4</li>
              <li>Item 5</li>
              <li>Item 1</li>
              <li>Item 2</li>
              <li>Item 3</li>
              <li>Item 4</li>
              <li>Item 5</li>
              <li>Item 1</li>
              <li>Item 2</li>
              <li>Item 3</li>
              <li>Item 4</li>
              <li>Item 5</li>
            </ul>
          </div>
        </div>
      </div>
    </div>

    所有问题都与.sub.container 上使用的内部height:100% 有关。从技术上讲,考虑到规范,这个高度应该不能达到auto,因为没有设置父高度,但是 Firefox 似乎能够评估这个高度。可能是由于嵌套的 flex 容器,我们可以在知道内容之前评估父高度,或者只是一个错误。

    Chrome 没有这样做,只是忽略了高度,这是合乎逻辑的行为。

    【讨论】:

    • 嗯,听起来不错,但为什么 Chrome 和 FF 之间的行为不同呢?谁是对的?
    • @MicheleMariotti 我投票支持 chrome,因为 FF 中存在违规行为(我将编辑我的答案)但很难说。
    • 其实Chrome好像是用declared高度作为参考,而FF用的是computed。如果您从.sub.container 中删除height:100%,则FF 呈现与Chrome 相同。因此,对于 FF 来说,100% 是一个有效的参考,对于 Chrome 来说不是。即使 Chrome 的行为看起来更准确,FF 似乎更有用。
    • @MicheleMariotti 完全是 ;) 我还进行了编辑以显示这一点...... FF 以某种方式进行了复杂的计算(不知道具体如何),这就是我正在谈论的违规行为
    【解决方案2】:

    也许height: fit-content 就是您要找的东西?我对你想要的结果有点困惑。

    html, body {
      height: 100%;
      margin: 0;
      padding: 0;
    }
    
    * {
      box-sizing: border-box;
    }
    
    div {
      padding: 10px;
    }
    
    .container {
      display: flex;
      flex-direction: column;
    }
    
    .content {
      flex: 1;
      max-height: 100%;
      overflow: auto;
    }
    
    .root.container {
      background-color: red;
      max-height: 100%;
      height: fit-content;
    }
    
    .sub.container {
      background-color: purple;
      height: 100%;
    }
    
    .root.header {
      background-color: lightblue;
    }
    
    .sub.header {
      background-color: lightgreen;
    }
    
    .root.content {
      background-color: yellow;
    }
    
    .sub.content {
      background-color: orange;
    }
    <div class="root container">
      <div class="root header">header</div>
      <div class="root content">
        <div class="sub container">
          <div class="sub header">menu</div>
          <div class="sub content">
            <ul>
              <li>Item 1</li>
              <li>Item 2</li>
              <li>Item 3</li>
              <li>Item 4</li>
              <li>Item 5</li>
              <li>Item 1</li>
              <li>Item 2</li>
              <li>Item 3</li>
              <li>Item 4</li>
              <li>Item 5</li>
              <li>Item 1</li>
              <li>Item 2</li>
              <li>Item 3</li>
              <li>Item 4</li>
              <li>Item 5</li>
              <li>Item 1</li>
              <li>Item 2</li>
              <li>Item 3</li>
              <li>Item 4</li>
              <li>Item 5</li>
              <li>Item 1</li>
              <li>Item 2</li>
              <li>Item 3</li>
              <li>Item 4</li>
              <li>Item 5</li>
              <li>Item 1</li>
              <li>Item 2</li>
              <li>Item 3</li>
              <li>Item 4</li>
              <li>Item 5</li>
              <li>Item 1</li>
              <li>Item 2</li>
              <li>Item 3</li>
              <li>Item 4</li>
              <li>Item 5</li>
              <li>Item 1</li>
              <li>Item 2</li>
              <li>Item 3</li>
              <li>Item 4</li>
              <li>Item 5</li>
              <li>Item 1</li>
              <li>Item 2</li>
              <li>Item 3</li>
              <li>Item 4</li>
              <li>Item 5</li>
              <li>Item 1</li>
              <li>Item 2</li>
              <li>Item 3</li>
              <li>Item 4</li>
              <li>Item 5</li>
              <li>Item 1</li>
              <li>Item 2</li>
              <li>Item 3</li>
              <li>Item 4</li>
              <li>Item 5</li>
            </ul>
          </div>
        </div>
      </div>
    </div>

    【讨论】:

    • 想要的结果其实就是你运行我的sn-p时看到的结果。尝试在 chrome 上运行您的 sn-p 以查看问题。 fit-contentauto 一样,不起作用。
    猜你喜欢
    • 2017-01-16
    • 2020-05-13
    • 1970-01-01
    • 2015-02-20
    • 2016-07-05
    • 1970-01-01
    • 2018-01-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多