解决方案
使用嵌套的弹性容器。
摆脱百分比高度。摆脱表格属性。摆脱vertical-align
。避免绝对定位。只需完全使用 flexbox。
将display: flex
应用于弹性项目(.item
),使其成为弹性容器。这会自动设置align-items: stretch
,告诉子元素(.item-inner
)扩展父元素的整个高度。
重要提示:为了使此方法起作用,请从弹性项目中删除指定的高度。如果子元素指定了高度(例如height: 100%
),则它将忽略来自父元素的align-items: stretch
。为了使默认的stretch
起作用,子元素的高度必须计算为auto
(完整说明)。
尝试这个(不更改HTML):
.container {
display: flex;
flex-direction: column;
height: 20em;
border: 5px solid black
}
.item {
display: flex;
flex: 1;
border-bottom: 1px solid white;
}
.item-inner {
display: flex;
flex: 1;
}
a {
display: flex;
flex: 1;
align-items: center;
background: orange;
}
<div class="container">
<div class="item">
<div class="item-inner">
<a>Button</a>
</div>
</div>
<div class="item">
<div class="item-inner">
<a>Button</a>
</div>
</div>
<div class="item">
<div class="item-inner">
<a>Button</a>
</div>
</div>
</div>
jsFiddle demo
解释
我的问题是,.item-inner { height: 100% }
在webkit(Chrome)中无法工作。
它无法工作,因为您正在以不符合规范传统实现的方式使用百分比高度。
10.5 内容高度: height
属性
百分比
指定一个百分比高度。百分比是相对于生成的框的包含块的高度计算的。如果未明确指定包含块的高度并且此元素未绝对定位,则该值计算为auto
。
自动
高度取决于其他属性的值。
换句话说,要使百分比高度在流动子级上起作用,父级必须具有设置的高度。
在您的代码中,顶层容器具有定义的高度:.container { height: 20em; }
第三级容器已定义高度:
.item-inner { height: 100%; }
但在它们之间,第二级容器 -
.item
- 没有定义高度。 Webkit 将其视为缺失的链接。
.item-inner
告诉 Chrome:给我
height: 100%
。Chrome 寻找父元素 (
.item
) 作为参考,并回应:100% 是相对于什么?我没有看到任何东西(忽略了存在的
flex: 1
规则)。因此,它按照规范应用
height: auto
(内容高度)。
另一方面,Firefox 现在接受父元素的 flex 高度作为子元素百分比高度的参考。IE11 和 Edge 也接受 flex 高度。
此外,如果与
flex-basis
一起使用(任何数字值都可以,
auto
不行,包括
flex-basis:0
),Chrome将接受
flex-grow
作为足够的父级参考。然而,截至本文撰写时,这种解决方案在Safari中失败了。
#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;
}
<div id="outer">
<div id="middle">
<div id="inner">
INNER
</div>
</div>
</div>
四种解决方案
1. 在所有父元素上指定高度
一个可靠的跨浏览器解决方案是在所有父元素上指定高度。这可以避免缺失链接,而 Webkit 浏览器则认为这是违反规范的。
请注意,min-height
和 max-height
不可接受。必须使用 height
属性。
更多细节请参见:使用 CSS 的 height
属性和百分比值
2. CSS 相对和绝对定位
将 position: relative
应用于父元素,将 position: absolute
应用于子元素。
使用 height: 100%
和 width: 100%
来设置子元素的大小,或使用偏移属性:top: 0
、right: 0
、bottom: 0
、left: 0
。
使用绝对定位时,父元素没有指定高度也可以使用百分比高度。
3. 删除不必要的HTML容器(建议)
是否需要在button
周围放置两个容器?为什么不删除.item
或.item-inner
,或者两者都删除?尽管button
元素有时作为弹性容器失败, 它们可以作为弹性项目。考虑将button
作为.container
或.item
的子级,并删除多余的标记。
这是一个例子:
.container {
height: 20em;
display: flex;
flex-direction: column;
border: 5px solid black
}
a {
flex: 1;
background: orange;
border-bottom: 1px solid white;
display: flex;
align-items: center;
justify-content: center;
}
<div class="container">
<a>Button</a>
<a>Button</a>
<a>Button</a>
</div>
4. 嵌套的 Flex 容器(推荐)
摆脱百分比高度。摆脱表格属性。摆脱 vertical-align
。避免使用绝对定位。只需完全使用 flexbox。
将 display: flex
应用于 flex 项 (.item
),使其成为一个 flex 容器。这会自动设置 align-items: stretch
,告诉子项 (.item-inner
) 扩展父项的整个高度。
重要提示:删除此方法中 flex 项的指定高度。 如果子元素有指定的高度 (例如,height: 100%
),那么它将忽略来自父元素的 align-items: stretch
。要使默认的 stretch
生效,子元素的高度必须计算为 auto
(完整解释)。
尝试这样做(不更改 HTML):
.container {
display: flex;
flex-direction: column;
height: 20em;
border: 5px solid black
}
.item {
display: flex;
flex: 1;
border-bottom: 1px solid white;
}
.item-inner {
display: flex;
flex: 1;
}
a {
display: flex;
flex: 1;
align-items: center;
background: orange;
}
<div class="container">
<div class="item">
<div class="item-inner">
<a>Button</a>
</div>
</div>
<div class="item">
<div class="item-inner">
<a>Button</a>
</div>
</div>
<div class="item">
<div class="item-inner">
<a>Button</a>
</div>
</div>
</div>
top:0
和left:0
才能按预期显示。 - AlexMA