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

时间:2018-02-03 01:52:03

标签: css css3 flexbox overflow

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

我希望能够确保给定的孩子具有最小身高,如果它有足够的内容来填充它。为了澄清,这里有一些额外的例子,假设总容器高度为1000px,并且所需的“最小高度与内容”为200px。左侧是盒子的自然高度,右侧是弹性容器内所需的高度。

// 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

(请注意,这些示例中较小的子项始终是第二个,但这应该以任意数量的子项的任何顺序工作。)

#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>

1 个答案:

答案 0 :(得分:1)

No, that is not possible with Flexbox, or CSS in general.

The reason is that CSS is not a programming language, and doesn't have any methods one can use to make those kind of calculations.


What is possible, using Flexbox, is to elaborate with its flex-shrink value, which with one control how a flex item share the remaining space, and in this case, a negative one.

Here I used each item's font-size's value (which in this case defines the height of the item) also for the flex-shrink, to show a possible end result.

What it does is simply, after each items content is subtracted, share the negative space like this, in e.g. the right column (and 18 is the sum of all items flex-shrink value):

  • c gets 4/18

  • d gets 12/18

  • e gets 2/18


These values can either be calculated server-side and assigned inline, or client-side using a script.

If this is not an option, a script will be needed to adjust each items minimum height


Stack snippet

#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>