绝对定位、百分比高度和 flexbox

Absolute positioning, percentage heights and flexbox

我想要一个具有最大高度(例如其容器的 50%)的 flexbox 容器。很简单吧?

.container {
  display: flex;
  flex-direction: column;
  border: 1px solid red;
  overflow: hidden;
  height: 50%;
  position: absolute;
}
.list {
  flex: 0 1 auto;
  overflow: auto;
}
.fixed {
  flex: 0 0 auto;
}
<div class="container">
    <header class="fixed">Header</header>
    <div class="list">
        <ul>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
        </ul>
    </div>
    <footer class="fixed">Footer</footer>
</div>

可行,但删除 position: absolute 后会增大 50% 以上(并且宽度会发生变化)。这是为什么?

.container {
  display: flex;
  flex-direction: column;
  border: 1px solid red;
  overflow: hidden;
  height: 50%;
}
.list {
  flex: 0 1 auto;
  overflow: auto;
}
.fixed {
  flex: 0 0 auto;
}
<div class="container">
    <header class="fixed">Header</header>
    <div class="list">
        <ul>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
        </ul>
    </div>
    <footer class="fixed">Footer</footer>
</div>

行为在规范中定义:

10.5 Content height: the height property

<percentage>

Specifies a percentage height.

The percentage is calculated with respect to the height of the generated box's containing block.

If the height of the containing block is not specified explicitly (i.e., it depends on content height), and this element is not absolutely positioned, the used height is calculated as if auto was specified.

所以,这里有两个要点:

  1. 当你的容器不是绝对定位的(即,它保持在流中)时,父级没有定义高度的事实意味着 height: 50% 解析为 height: auto(内容的高度)。

    如果您设置 body { height: 100vh },您的容器将占据 50% 的高度。

body {
  height: 100vh;
}

.container {
  display: flex;
  flex-direction: column;
  border: 1px solid red;
  overflow: hidden;
  height: 50%;
}

.list {
  flex: 0 1 auto;
  overflow: auto;
}

.fixed {
  flex: 0 0 auto;
}
<div class="container">
  <header class="fixed">Header</header>
  <div class="list">
    <ul>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
    </ul>
  </div>
  <footer class="fixed">Footer</footer>
</div>

  1. 当您的容器是绝对定位时,height: auto 规则不适用,height: 50% 按预期工作。

    此外,流入块级元素占用其容器的宽度。一旦应用绝对定位——从文档流中移除元素——"take the width of the parent" 规则不再适用,你需要指定容器的宽度,或定义偏移属性(即 left, right, 等等).

.container {
  display: flex;
  flex-direction: column;
  border: 1px solid red;
  overflow: hidden;
  height: 50%;
  position: absolute;
  
  /* new */
  left: 0;
  right: 0;
  /* or this */
  /* width: 100%; */
}

.list {
  flex: 0 1 auto;
  overflow: auto;
}

.fixed {
  flex: 0 0 auto;
}

/* new */
 * { box-sizing: border-box; }
<div class="container">
  <header class="fixed">Header</header>
  <div class="list">
    <ul>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
      <li>Item</li>
    </ul>
  </div>
  <footer class="fixed">Footer</footer>
</div>

更多详情:

  • Block elements consume the full width of their parent, by default.