Chrome / Safari无法填充Flex父级的100%高度


235

我想要一个具有特定高度的垂直菜单。

每个孩子必须填满父母的身高,并且中间对齐文本。

孩子的数量是随机的,因此我必须使用动态值。

Div .container包含随机数量的子代(.item),这些子代始终必须填充父代的高度。为此,我使用了flexbox。

为了使文本中间对齐,我使用了display: table-cell技巧。但是使用桌子显示器需要使用100%的高度。

我的问题是.item-inner { height: 100% }无法在webkit(Chrome)中使用。

  1. 有解决此问题的方法吗?
  2. 还是有另一种方法使.item文本全部垂直于中间对齐,从而全部填充父级的高度?

此处的示例jsFiddle,应在Firefox和Chrome中查看

.container {
  height: 20em;
  display: flex;
  flex-direction: column;
  border: 5px solid black
}
.item {
  flex: 1;
  border-bottom: 1px solid white;
}
.item-inner {
  height: 100%;
  width: 100%;
  display: table;
}
a {
  background: orange;
  display: table-cell;
  vertical-align: middle;
}
<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>



3
这与OP没有特别的关系,但对于因“野生动物园显示绝对高度100%无法正常工作”或类似原因而落在此处的Google员工来说可能与此有关。我在flex容器中有一个这样的元素,必须指定top:0left:0使其按预期显示。
AlexMA

Answers:


408

使用嵌套的伸缩容器。

摆脱百分比高度。摆脱表属性。摆脱vertical-align。避免绝对定位。一直坚持使用flexbox。

应用于display: flexflex项目(.item),使其成为flex容器。这会自动设置align-items: stretch,告诉孩子(.item-inner)扩大父母的整个身高。

重要提示:从弹性项目中删除指定的高度,此方法才能起作用。如果孩子有指定的身高(例如height: 100%),那么它将忽略align-items: stretch来自父母的身高。为了使stretch默认设置生效,孩子的身高必须计算为auto (完整说明)。

试试看(HTML不变):

jsFiddle演示


说明

我的问题是.item-inner { height: 100% }无法在webkit(Chrome)中使用。

它不起作用,因为您使用的百分比高度与规范的传统实现方式不一致。

10.5内容高度:height属性

percent
指定百分比高度。相对于生成的盒子的包含块的高度计算百分比。如果未明确指定包含块的高度,并且此元素未绝对定位,则该值将计算为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也接受弯曲高度。

此外,如果与(任何数字值(不会),包括在内)结合使用,Chrome将接受flex-grow作为适当的父级参考。但是,在撰写本文时,此解决方案在Safari中失败。flex-basisautoflex-basis: 0


四种解决方案

1.在所有父元素上指定高度

可靠的跨浏览器解决方案是在所有父元素上指定高度。这样可以防止丢失链接,基于Webkit的浏览器会认为这些链接违反了规范。

请注意,min-heightmax-height是不可接受的。它必须是height属性。

此处更多详细信息: 使用CSS height属性和百分比值

2. CSS相对和绝对定位

适用position: relative于父母和position: absolute孩子。

使用height: 100%和调整子项的大小width: 100%,或使用offset属性:top: 0right: 0bottom: 0left: 0

通过绝对定位,百分比高度可以在父级上没有指定高度的情况下工作。

3.删除不必要的HTML容器(推荐)

是否需要两个容器button?为什么不删除.item.item-inner,或两者都不删除?尽管button元素有时会作为弹性容器失败,但它们可以是弹性项目。考虑让button孩子成为.container.item,并删除不必要的标记。

这是一个例子:

4.嵌套的Flex容器(推荐)

摆脱百分比高度。摆脱表属性。摆脱vertical-align。避免绝对定位。一直坚持使用flexbox。

应用于display: flexflex项目(.item),使其成为flex容器。这会自动设置align-items: stretch,告诉孩子(.item-inner)扩大父母的整个身高。

重要提示:从弹性项目中删除指定的高度,此方法才能起作用。如果孩子有指定的身高(例如height: 100%),那么它将忽略align-items: stretch来自父母的身高。为了使stretch默认设置生效,孩子的身高必须计算为auto (完整说明)。

试试看(HTML不变):

jsFiddle


3
我上的使用高度,是我的问题:汽车
Alfrex92

从这篇出色文章的解释链接中获得的一些评论-“ align-items:Stretch”使flex子级在容器的横轴上展开-也就是说,将子级拉伸到一定高度,flex容器应具有flex-direction作为行。
littlewhywhat

3
我可以确认使用嵌套flex容器效果最好。我们在菜单中不一致地使用了flexbox。代替在父容器上使用flex:1和display:flex,我们在某些地方使用height:100%。替换了相应的定义后,所有操作均按预期进行。感谢@Michael_B的提示!:)
flocbit

1
@ JamesHarrington,CSS随时间增长并且非常复杂;-)
DerMike

每个解决方案应该是不同的答案。如何以这种方式在特定解决方案中投票?
JP_


10

为容器指定flex属性对我有用:

.container {
    flex: 0 0 auto;
}

这样可以确保高度已设置且不会增大。


6

对于Mobile Safari,有一个浏览器修复程序。您需要为iOS设备添加-webkit-box

例如

display: flex;
display: -webkit-box;
flex-direction: column;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-webkit-flex-direction: column;
align-items: stretch;

如果您将align-items: stretch;属性用于父元素,请height : 100%从子元素中删除。


2

我在iOS 8、9和10中遇到过类似的问题,上面的信息无法解决,但是经过一天的努力,我确实找到了解决方案。当然,它不适用于所有人,但在我的情况下,我的物品堆放在一列中,当高度应为内容高度时,高度为0。将CSS切换为行换行可解决此问题。仅当您只有一个项目并且将它们堆叠在一起时,此方法才有效,但是由于花了我一天的时间才能找到答案,所以我认为我应该分享自己的解决方案!

.wrapper {
    flex-direction: column; // <-- Remove this line
    flex-direction: row; // <-- replace it with
    flex-wrap: wrap; // <-- Add wrapping
}

.item {
    width: 100%;
}

0

我有一个类似的错误,但是使用的是固定高度而不是百分比。它也是体内的弹性容器(没有指定高度)。似乎在Safari上,出于某种原因,我的flex容器的高度为9px,但在所有其他浏览器中,它都显示了样式表中指定的正确100px高度。

通过将heightmin-height属性都添加到CSS类,我设法使其正常工作。

以下内容适用于Safari 13.0.4和Chrome 79.0.3945.130:

.flex-container {
  display: flex;
  flex-direction: column;
  min-height: 100px;
  height: 100px;
}

希望这可以帮助!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.