flex-grow 子元素高度百分比无效

chrome 浏览器,flex 布局,设置 flex-grow 部分的子元素无法用百分比适应父元素尺寸,而 flex:1 可以。例子如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<!DOCTYPE html>
<html>
<style>
#wrapper {
height: 800px;
display: flex;
flex-direction: column;
}
header, footer {
height: 30px;
}
main {
/* flex: 1; */
flex-grow: 1;
background-color: red;
}
#test {
height: 100%;
background-color: yellow;
}
</style>
<body>
<div id="wrapper">
<header>
header
</header>
<main>
<div id="test">
我是id为test的div,我设置了height: 100%
</div>
</main>
<footer>
footer
</footer>
</div>
</body>
</html>

当 main 设置为 flex-grow 时,子元素设置 100% 无效。不能撑大到父元素的高度。

为什么呢:
看W3C上关于高度的定义:

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 and this element is not absolutely positioned, the value computes to auto.
auto
The height depends on the values of other properties.

即:如果高度设置百分比,那百分比是计算的相对于包含块的高度。如果包含块高度未指定(取决于内容高度),而且此元素不是绝对定位,那该百分比值就等同于auto。

此外,chrome 也接受:当父元素用了 flex-grow ,同时也有 flex-basis 属性(固定的任何值,包括flex-basis:0)时,子元素可以引用父元素的高度。

即此例子是可以的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<!DOCTYPE html>
<html>
<style>
#outer {
display: flex;
flex-direction: column;
height: 300px;
background-color: white;
border: 1px solid red;
}
#middle {
flex-grow: 1;
flex-basis: 1px;
background-color: yellow;
}
#inner {
height: 100%;
background-color: lightgreen;
}
</style>
<body>
<div id="outer">
<div id="middle">
<div id="inner">
INNER
</div>
</div>
</div>
</body>
</html>

那为什么 flex:1 可以呢?
flex 是 flex-grow,flex-shrink,flex-basis 的缩写。
flex(default)

1
2
3
flex-grow: 0
flex-shrink: 1
flex-basis: auto

flex:1

1
2
3
flex-grow: 1
flex-shrink: 1
flex-basis: 0

flex-grow:1

1
2
3
flex-grow: 1;
flex-shrink: 1;
flex-basis: auto;

所以二者主要区别在于flex-basis。

flex-basis: auto:main 元素的高度由内容高度来决定,flex-grow 分配剩余空间(800px-60px),但是是一个伪分配,flex-grow 更像是一个min-height。
flex-basis: 0:等同于 main 元素的高度是0,flex-grow 将剩余空间实实在在的分配给 main 元素,给 main 元素增加高度。

解决办法是:

  1. 给父元素指定一个固定高度, min-height 或 max-height 不行。
  2. 将父元素 main 设置为 relative,子元素设置 absolute 使其脱离文档流定位。
  3. 嵌套 flex 布局(推荐用法)。设置 main 为display:flex作为 flex 容器,align-items 默认值为 stretch ,这样子元素会自动拉伸以适应父容器的高度。但要注意:移除内部元素的高度属性(height:100%),否则会忽略父元素的align-items:stretch 。为了使 stretch 属性起作用,内部高度必须设置为 auto 。

参考链接
http://zhoon.github.io/css3/2014/08/23/flex.html
https://stackoverflow.com/questions/33636796/chrome-safari-not-filling-100-height-of-flex-parent