约束多个滚动的flex元素的高度

Constrain the height of multiple scrolling flex elements

当具有多个滚动的 flex 容器 children 溢出时,children 共享容器的高度与其内容的自然高度成比例(左侧代码示例)。但是,当一个 child 的高度明显大于另一个的高度时,这可能会变得极端(右侧代码示例)。较小的 child 基本上变得不可见,或者至少小得可笑。解决这个问题的一种方法是在每个 children 上设置一个 min-height,但是如果 children 没有足够的内容,那会浪费 space填充最小高度。

我想要做的是确保给定的 child 具有最小高度 如果 它有足够的内容来填充它。为了澄清,这里有一些额外的例子,假设容器的总高度为 1000 像素,所需的 "minimum height with content" 为 200 像素。左边是盒子的自然高度,右边是弹性容器内所需的高度。

// Total height is smaller than container; no issues
700, 200       =>  700, 200
500, 500       =>  500, 500

// Smaller child's content is less than minimum height;
// bigger child should fill the space
1000, 50       =>  950, 50
6000, 100      =>  900, 100

// Proportional scaling does not violate minimum height
7000, 3000     =>  700, 300
8000, 2000     =>  800, 200

// Proportional scaling *does* violate minimum height
9000, 1000     =>  800, 200
1000000, 1000  =>  800, 200

(请注意,这些示例中较小的 child 始终是第二个,但这应该以任何顺序与任何数量的 children 一起使用。)

#box-a {
  background-color: lightblue;
  font-size: 8em;
}

#box-b {
  background-color: lightgoldenrodyellow;
  font-size: 4em;
}

#box-c {
  background-color: lightblue;
  font-size: 15em;
}

#box-d {
  background-color: lightgoldenrodyellow;
  font-size: 4em;
}

.content {
  height: 200px;
  width: 200px;
  border: 1px solid black;
}

.header {
  background-color: lightgreen;
}

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

.scrolling {
  overflow-y: auto;
  overflow-x: hidden;
}
<div style="width:600px; display:flex; justify-content: space-between">
    <div class="content container">
      <div class="header">
        Header
      </div>
      <div class="container">
        <div id="box-a" class="container">
          <div class="scrolling">Box A</div>
        </div>
        <div id="box-b" class="container">
          <div class="scrolling">Box B</div>
        </div>
      </div>
    </div>

    <div class="content container">
      <div class="header">
        Header
      </div>
      <div class="container">
        <div id="box-c" class="container">
          <div class="scrolling">Box C</div>
        </div>
        <div id="box-d" class="container">
          <div class="scrolling">Box D</div>
        </div>
      </div>
    </div>
  </div>
</div>

不,这对于 Flexbox 或一般来说 CSS 是不可能的。

原因是 CSS 不是一种编程语言,也没有任何方法可以用来进行此类计算。


使用 Flexbox 的可能是用它的 flex-shrink 值来详细说明,它可以控制一个 flex 项目如何共享剩余的 space,并且在这种情况下,负数。

这里我还为 flex-shrink 使用了每个项目的字体大小值(在本例中定义了项目的高度)以显示可能的最终结果。

它的作用很简单,在减去每个项目的内容后,像这样共享负值space,例如右栏(18 是所有项目 flex-shrink 值的总和):

  • c 得到 4/18

  • d 得到 12/18

  • e 得到 2/18


这些值可以在服务器端计算并内联分配,也可以在客户端使用脚本计算。

如果这不是一个选项,则需要一个脚本来调整每个项目最小高度


堆栈片段

#box-a {
  background-color: lightblue;
  font-size: 8em;
  flex: 0 8 auto;
}

#box-b {
  background-color: lightgoldenrodyellow;
  font-size: 4em;
  flex: 0 4 auto;
}

#box-c {
  background-color: lightblue;
  font-size: 4em;
  flex: 0 4 auto;
}

#box-d {
  background-color: lightgoldenrodyellow;
  font-size: 12em;
  flex: 0 12 auto;
}

#box-e {
  background-color: lightblue;
  font-size: 2em;
  flex: 0 2 auto;
}

.content {
  height: 200px;
  width: 200px;
  border: 1px solid black;
}

.header {
  background-color: lightgreen;
}

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

.scrolling {
  overflow-y: auto;
  overflow-x: hidden;
}
<div style="width:500px; display:flex; justify-content: space-between">
    <div class="content container">
      <div class="header">
        Header
      </div>
      <div class="container">
        <div id="box-a" class="container">
          <div class="scrolling">Box A</div>
        </div>
        <div id="box-b" class="container">
          <div class="scrolling">Box B</div>
        </div>
      </div>
    </div>

    <div class="content container">
      <div class="header">
        Header
      </div>
      <div class="container">
        <div id="box-c" class="container">
          <div class="scrolling">Box C</div>
        </div>
        <div id="box-d" class="container">
          <div class="scrolling">Box D</div>
        </div>
        <div id="box-e" class="container">
          <div class="scrolling">Box C</div>
        </div>
      </div>
    </div>
</div>