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

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

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

Div .container包含随机数量的子元素(.item),这些子元素总是要填充父元素的高度。为了实现这一点,我使用了flexbox。

为了使链接与文本对齐到中间,我使用显示:表格单元格技术。但是使用表格显示需要使用100%的高度。

我的问题是。item-inner {height: 100%}不工作在webkit (Chrome)。

有解决这个问题的方法吗? 或者有不同的技术,使所有的。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>


解决方案

使用嵌套的伸缩容器。

去掉高度百分比。删除表属性。去掉垂直对齐。避免绝对定位。一直用flexbox就行了。

将display: flex应用于伸缩项目(.item),使其成为伸缩容器。这将自动设置align-items: stretch,它告诉子对象(.item-inner)展开父对象的全部高度。

重要提示:要使此方法生效,请从伸缩项目中删除指定的高度。如果子对象指定了高度(例如:height: 100%),那么它将忽略来自父对象的align-items: stretch。为了使拉伸默认工作,孩子的高度必须计算为自动(完整解释)。

试试这个(不改变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%}不工作 webkit(铬)。

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

10.5内容高度:高度属性 percentage高度百分比。百分比是根据生成的盒子的高度计算的 包含块。如果包含块的高度不是 如果显式指定且该元素不是绝对定位,则该值计算为auto。 auto高度取决于其他属性的值。

换句话说,要使百分比高度作用于流子进程,父进程必须有一个设置的高度。

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

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

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

.item-inner告诉Chrome:给我高度:100%。Chrome查看父(.item)的参考和响应:100%的什么?我没有看到任何东西(忽略flex: 1规则)。因此,它应用高度:auto(内容高度),符合规范。

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

此外,如果与flex- base一起使用,Chrome将接受flex-grow作为适当的父引用(任何数值都可以(auto won't),包括flex-basis: 0)。然而,在撰写本文时,这个解决方案在Safari中失败了。

#{外 显示:flex; flex-direction:列; 身高:300 px; 背景颜色:白色; 边框:1px纯红色; } #{中间 flex-grow: 1; flex-basis: 1 px; 背景颜色:黄色; } #{内部 高度:100%; background - color: lightgreen; } < div id = "外" > < div id =“中间”> < div id = "内部" > 内心的 < / div > < / div > < / div >


四个解决方案

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

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

注意,min-height和max-height是不可接受的。它一定是高度性质。

更多细节在这里:使用CSS高度属性和百分比值

2. CSS相对和绝对定位

应用位置:相对于父节点,位置:绝对于子节点。

为子元素设置高:100%和宽:100%的大小,或者使用offset属性:top: 0, right: 0, bottom: 0, left: 0。

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

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

按钮周围需要两个容器吗?为什么不删除。item或。item-inner,或者两者都删除?尽管按钮元素有时不能作为伸缩容器,但它们可以是伸缩项。考虑将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>

4. 嵌套Flex容器(推荐)

去掉高度百分比。删除表属性。去掉垂直对齐。避免绝对定位。一直用flexbox就行了。

将display: flex应用于伸缩项目(.item),使其成为伸缩容器。这将自动设置align-items: stretch,它告诉子对象(.item-inner)展开父对象的全部高度。

重要提示:要使此方法生效,请从伸缩项目中删除指定的高度。如果子对象指定了高度(例如:height: 100%),那么它将忽略来自父对象的align-items: stretch。为了使拉伸默认工作,孩子的高度必须计算为自动(完整解释)。

试试这个(不改变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>

js小提琴

解决方案:在.item-inner中删除高度: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。

Ex.

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;属性,则从子元素中删除高度:100%。

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

.container {
    flex: 0 0 auto;
}

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