ChatGPT解决这个技术问题 Extra ChatGPT

Chrome / Safari 未填充 flex 父级的 100% 高度

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

每个子项必须填充父项的高度并具有居中对齐的文本。

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

Div .container 包含随机数量的子项 (.item),它们总是必须填充父项的高度。为了实现这一点,我使用了 flexbox。

为了制作与中间对齐的文本链接,我使用了 display: table-cell 技术。但是使用桌面显示器需要使用 100% 的高度。

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

有解决这个问题的方法吗?或者是否有一种不同的技术可以使所有 .item 填充父级的高度,文本垂直对齐到中间?

Example here jsFiddle, should be viewed in Firefox and Chrome

.container { 高度:20em;显示:弯曲;弹性方向:列;边框:5px 纯黑色 } .item { flex: 1;边框底部:1px 纯白色; } .item-inner { 高度:100%;宽度:100%;显示:表格; } a { 背景:橙色;显示:表格单元格;垂直对齐:中间; }

这与 OP 没有特别相关,但可能与因“safari display absolute height 100% doesn't work”或类似内容而登陆这里的谷歌用户相关。我在 flex 容器中有这样的元素,必须指定 top:0left:0 才能使其按预期显示。

M
Michael Benjamin

解决方案

使用嵌套的弹性容器。

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

display: flex 应用于弹性项目 (.item),使其成为弹性容器。这会自动设置 align-items: stretch,它告诉子 (.item-inner) 扩展父的完整高度。

重要提示:从 flex 项中删除指定的高度以使此方法起作用。 如果子项具有指定的高度(例如 height: 100%),那么它将忽略来自父项的 align-items: stretch。要使 stretch 默认值起作用,孩子的身高必须计算为 auto (full explanation)。

试试这个(不更改 HTML):

.container { 显示:弹性;弹性方向:列;高度:20em;边框:5px 纯黑色 } .item { display: flex; /* 新的;嵌套的 flex 容器 */ flex: 1;边框底部:1px 纯白色; } .item-inner { 显示:弹性; /* 新的;嵌套的 flex 容器 */ flex: 1; /* 新 */ /* 高度:100%; <-- 删除;不必要的 */ /* 宽度:100%; <-- 删除;不必要的 */ /* display: table; <-- 删除;不必要的 */ } a { display: flex; /* 新的;嵌套的 flex 容器 */ flex: 1; /* 新 */ align-items: center; /* 新的;垂直居中文本 */ 背景:橙色; /* 显示:表格单元格; <-- 删除;不必要的 */ /* 垂直对齐:中间; <-- 删除;不必要的 */ }

jsFiddle demo

解释

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

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

10.5 内容高度:height 属性百分比 指定百分比高度。该百分比是相对于生成框的包含块的高度计算的。如果未明确指定包含块的高度并且此元素不是绝对定位的,则该值计算为 auto。 auto 高度取决于其他属性的值。

换句话说,要使百分比高度适用于流入的孩子,父母必须有一个设定的高度。

在您的代码中,顶级容器具有定义的高度:.container { height: 20em; }

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

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

.item-inner 告诉 Chrome:给我height: 100%。 Chrome 会查看父级 (.item) 以供参考并回应:100% 的什么?我什么也没看到(忽略那里的 flex: 1 规则)。因此,它根据规范应用 height: auto(内容高度)。

另一方面,Firefox 现在接受父母的弹性高度作为孩子身高百分比的参考。 IE11 和 Edge 也接受弹性高度。

此外,如果将 flex-growflex-basis 结合使用,Chrome 将接受 flex-grow 作为适当的父引用(任何数值都有效(auto 无效),包括 flex-basis: 0)。然而,在撰写本文时,此解决方案在 Safari 中失败。

#outer { 显示:弹性;弹性方向:列;高度:300px;背景颜色:白色;边框:1px 纯红色; } #middle { 弹性增长:1;弹性基础:1px;背景颜色:黄色; } #inner { 高度:100%;背景颜色:浅绿色; }

INNER

四种解决方案

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

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

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

更多详细信息:Working with the CSS height property and percentage values

2. CSS 相对和绝对定位

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

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

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

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

button 周围是否需要两个容器?为什么不删除 .item.item-inner,或两者都删除?尽管 button elements sometimes fail as flex containers,它们可以是弹性项目。考虑将 button 设为 .container.item 的子节点,并删除无偿标记。

这是一个例子:

.container { 高度:20em;显示:弯曲;弹性方向:列;边框:5px 纯黑色 } a { flex: 1;背景:橙色;边框底部:1px 纯白色;显示:弯曲; /* 嵌套的 flex 容器(用于对齐文本) */ align-items: center; /* 垂直居中文本 */ justify-content: center; /* 水平居中文本 */ }

4. 嵌套 Flex 容器(推荐)

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

display: flex 应用于弹性项目 (.item),使其成为弹性容器。这会自动设置 align-items: stretch,它告诉子 (.item-inner) 扩展父的完整高度。

重要提示:从 flex 项中删除指定的高度以使此方法起作用。 如果子项具有指定的高度(例如 height: 100%),那么它将忽略来自父项的 align-items: stretch。要使 stretch 默认值起作用,孩子的身高必须计算为 auto (full explanation)。

试试这个(不更改 HTML):

.container { 显示:弹性;弹性方向:列;高度:20em;边框:5px 纯黑色 } .item { display: flex; /* 新的;嵌套的 flex 容器 */ flex: 1;边框底部:1px 纯白色; } .item-inner { 显示:弹性; /* 新的;嵌套的 flex 容器 */ flex: 1; /* 新 */ /* 高度:100%; <-- 删除;不必要的 */ /* 宽度:100%; <-- 删除;不必要的 */ /* display: table; <-- 删除;不必要的 */ } a { display: flex; /* 新的;嵌套的 flex 容器 */ flex: 1; /* 新 */ align-items: center; /* 新的;垂直居中文本 */ 背景:橙色; /* 显示:表格单元格; <-- 删除;不必要的 */ /* 垂直对齐:中间; <-- 删除;不必要的 */ }

jsFiddle


我使用 height:auto 解决了我的问题
只是从这篇很棒的帖子的解释链接中摘录的一些评论-“align-items:stretch”使flex子项在容器的横轴上扩展-即将子项拉伸到高度,flex容器应该具有flex-direction作为行。
我可以确认使用嵌套的弹性容器效果最好。我们在菜单中不一致地使用了 flexbox。我们没有在父容器上使用 flex: 1 和 display: flex ,而是在某些地方使用了 height: 100% 。在我们替换了相应的定义后,一切都按预期工作。感谢@Michael_B 的提示! :)
@JamesHarrington,CSS 随着时间的推移而增长并且很复杂;-)
每个解决方案都应该是不同的答案。我怎样才能以这种方式对特定解决方案进行投票?
h
huseyin39

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

.container {
    flex: 0 0 auto;
}

这样可以确保设置高度并且也不会增长。


为我修好了!多么救命啊。
我非常希望它能够工作,但我最终将容器从视口底部移开
为我工作。太感谢了。在此之前不明白为什么重定向到另一个页面时我的高度在 safari 上只有 1px。
n
nghiepit

解决方法:去掉.item-inner中的height: 100%,在.item中添加display: flex

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


谢谢,这对我有帮助。 flex 孩子会自动拉伸到容器的高度吗?这就是为什么这有效吗?
@ReeceKenney,是的,你的问题。这在我的回答中得到了解释。参见解决方案#4。
N
Narasinghe

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


天哪,非常感谢你让我免于头痛! display: -webkit-box; 正是我所需要的。事实证明,即使在 2020 年末,iOS 设备仍然没有可预测的 flex 支持
D
Designer023

我在 iOS 8、9 和 10 中遇到过类似的问题,上面的信息无法修复它,但是经过一天的工作后我确实找到了解决方案。当然,它不适用于所有人,但在我的情况下,我的项目被堆叠在一列中,并且当它应该是内容高度时高度为 0。将 css 切换为 row 并 wrap 解决了这个问题。这仅在您有一个项目并且它们堆叠时才有效,但由于我花了一天时间才发现这一点,我想我应该分享我的修复!

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

.item {
    width: 100%;
}