Chrome / Safari没有填充flex父控件的100%高度

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

每个子元素必须填充父元素的高度,并且文本必须居中对齐。

子节点的数量是随机的,所以我必须使用动态值。

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>

221772 次浏览

解决方案

使用嵌套的伸缩容器。

去掉高度百分比。删除表属性。去掉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;                      /* new; nested flex container */
flex: 1;
border-bottom: 1px solid white;
}


.item-inner {
display: flex;                      /* new; nested flex container */
flex: 1;                            /* new */


/* height: 100%;                    <-- remove; unnecessary */
/* width: 100%;                     <-- remove; unnecessary */
/* display: table;                  <-- remove; unnecessary */
}


a {
display: flex;                      /* new; nested flex container */
flex: 1;                            /* new */
align-items: center;                /* new; vertically center text */
background: orange;


/* display: table-cell;             <-- remove; unnecessary */
/* vertical-align: middle;          <-- remove; unnecessary */
}
<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(铬)。< / p >

它不能工作,因为您使用的百分比高度的方式不符合规范的传统实现。

10.5内容高度:height属性

百分比
高度百分比。百分比是根据生成的盒子的高度计算的 包含块。如果包含块的高度不是 如果显式指定且该元素不是绝对定位,则该值计算为auto

汽车
高度取决于其他属性的值。

换句话说,要使percentage height作用于流子对象,父对象必须有一个设置的高度。

在你的代码中,顶层容器有一个定义好的高度:.container { height: 20em; }

第三级容器有一个定义的高度:.item-inner { height: 100%; }

但在它们之间,第二级容器–.item mdash;有一个定义的高度。Webkit认为这是一个缺失的环节。

.item-inner告诉Chrome: 给我height: 100%。Chrome查找父(.item)引用并响应:100%什么?我什么都没看见(忽略那里的flex: 1规则)。因此,它根据规范应用height: auto(内容高度)。

另一方面,Firefox现在接受父节点的伸缩高度作为子节点高度百分比的参考。IE11和Edge也接受弯曲高度。

此外,Chrome将接受flex-grow作为适当的父引用如果与flex-basis一起使用(任何数值都可以(auto不行),包括flex-basis: 0)。然而,在撰写本文时,这个解决方案在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>


四个解决方案

< em > 1。指定所有父元素的高度

一个可靠的跨浏览器解决方案是在所有父元素上指定高度。这可以防止缺少链接,因为基于webkit的浏览器认为缺少链接违反了规范。

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

更多细节:使用CSS height属性和百分比值

< em > 2。CSS相关&绝对定位< / em >

position: relative应用于父类,将position: absolute应用于子类。

height: 100%width: 100%调整子对象的大小,或者使用偏移量属性:top: 0right: 0bottom: 0left: 0

使用绝对定位,百分比高度可以在父节点上不指定高度的情况下工作。

< em > 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;                   /* nested flex container (for aligning text) */
align-items: center;             /* center text vertically */
justify-content: center;         /* center text horizontally */
}
<div class="container">
<a>Button</a>
<a>Button</a>
<a>Button</a>
</div>

< em > 4。嵌套的Flex容器(推荐)

去掉高度百分比。删除表属性。去掉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;                      /* new; nested flex container */
flex: 1;
border-bottom: 1px solid white;
}


.item-inner {
display: flex;                      /* new; nested flex container */
flex: 1;                            /* new */


/* height: 100%;                    <-- remove; unnecessary */
/* width: 100%;                     <-- remove; unnecessary */
/* display: table;                  <-- remove; unnecessary */
}


a {
display: flex;                      /* new; nested flex container */
flex: 1;                            /* new */
align-items: center;                /* new; vertically center text */
background: orange;


/* display: table-cell;             <-- remove; unnecessary */
/* vertical-align: middle;          <-- remove; unnecessary */
}
<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

解决方法:在.item-inner中删除height: 100%,在.item中添加display: flex

演示:https://codepen.io/tronghiep92/pen/NvzVoo

我在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%;
}

对于移动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%

为容器指定一个flex属性对我来说很有用:

.container {
flex: 0 0 auto;
}

这确保了高度的设置,也不会增加。