CSS Chrome / Safari 未填充 100% 的 flex 父级高度
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/33636796/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Chrome / Safari not filling 100% height of flex parent
提问by Ricardo Casta?eda
I want to have a vertical menu with a specific height.
我想要一个具有特定高度的垂直菜单。
Each child must fill the height of the parent and have middle-aligned text.
每个子项必须填充父项的高度并具有居中对齐的文本。
The number of children is random, so I have to work with dynamic values.
孩子的数量是随机的,所以我必须使用动态值。
Div .container
contains a random number of children (.item
) that always have to fill the height of the parent. To achieve that I used flexbox.
Div.container
包含随机数量的子.item
节点( ),它们总是必须填充父节点的高度。为了实现这一点,我使用了 flexbox。
For making links with text aligned to the middle I am using display: table-cell
technique. But using table displays requires using a height 100%.
为了制作与中间对齐的文本的链接,我使用了display: table-cell
技术。但是使用表格显示需要使用高度 100%。
My problem is that .item-inner { height: 100% }
is not working in webkit (Chrome).
我的问题是.item-inner { height: 100% }
在 webkit (Chrome) 中不起作用。
- Is there a fix for this problem?
- Or is there a different technique to make all
.item
fill the height of the parent with text vertical aligned to middle?
- 这个问题有解决办法吗?
- 或者是否有一种不同的技术可以使
.item
文本垂直对齐到中间来填充父级的高度?
Example here jsFiddle, should be viewed in Firefox and Chrome
此处示例 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>
回答by Michael Benjamin
Solution
解决方案
Use nested flex containers.
使用嵌套的弹性容器。
Get rid of percentage heights. Get rid of table properties. Get rid of vertical-align
. Avoid absolute positioning. Just stick with flexbox all the way through.
摆脱百分比高度。摆脱表格属性。摆脱vertical-align
. 避免绝对定位。一直坚持使用 flexbox。
Apply display: flex
to the flex item (.item
), making it a flex container. This automatically sets align-items: stretch
, which tells the child (.item-inner
) to expand the full height of the parent.
应用于display: flex
弹性项目 ( .item
),使其成为弹性容器。这会自动设置align-items: stretch
,它告诉子.item-inner
节点( ) 扩展父节点的整个高度。
Important: Remove specified heights from flex items for this method to work.If a child has a height specified (e.g. height: 100%
), then it will ignore the align-items: stretch
coming from the parent. For the stretch
default to work, the child's height must compute to auto
(full explanation).
重要提示:从 flex 项目中删除指定的高度以使此方法起作用。如果孩子有指定的高度(例如height: 100%
),那么它将忽略align-items: stretch
来自父母的身高。对于stretch
默认的工作,孩子的身高必须计算到auto
(充分的解释)。
Try this (no changes to HTML):
试试这个(对 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>
Explanation
解释
My problem is that
.item-inner { height: 100% }
is not working in webkit (Chrome).
我的问题是
.item-inner { height: 100% }
在 webkit (Chrome) 中不起作用。
It's not working because you're using percentage height in a way that doesn't conform with the traditional implementation of the spec.
它不起作用,因为您以不符合规范的传统实现的方式使用百分比高度。
10.5 Content height: the
height
propertypercentage
Specifies a percentage height. The percentage is calculated with respect to the height of the generated box's containing block. If the height of the containing block is not specified explicitly and this element is not absolutely positioned, the value computes toauto
.auto
The height depends on the values of other properties.
百分比
指定百分比高度。该百分比是根据生成的框的包含块的高度计算的。如果未明确指定包含块的高度并且此元素不是绝对定位,则该值计算为auto
。auto
高度取决于其他属性的值。
In other words, for percentage height to work on an in-flow child, the parent musthave a set height.
换句话说,要使百分比高度适用于流入的孩子,父母必须有一个设定的高度。
In your code, the top-level container has a defined height: .container { height: 20em; }
在您的代码中,顶级容器具有定义的高度: .container { height: 20em; }
The third-level container has a defined height: .item-inner { height: 100%; }
三级容器具有定义的高度: .item-inner { height: 100%; }
But between them, the second-level container – .item
– does nothave a defined height. Webkit sees that as a missing link.
但它们之间,二级容器.item
————并没有明确的高度。Webkit 认为这是一个缺失的环节。
.item-inner
is telling Chrome: give me height: 100%
. Chrome looks to the parent (.item
) for reference and responds: 100% of what? I don't see anything(ignoring the flex: 1
rule that is there). As a result, it applies height: auto
(content height), in accordance with the spec.
.item-inner
正在告诉 Chrome:给我height: 100%
。Chrome 向父 ( .item
) 寻求参考并回答:100% 什么?我什么也没看到(忽略flex: 1
那里的规则)。因此,它height: auto
根据规范适用(内容高度)。
Firefox, on the other hand, now accepts a parent's flex height as a reference for the child's percentage height. IE11 and Edge accept flex heights, as well.
另一方面,Firefox 现在接受父级的 flex 高度作为子级百分比高度的参考。IE11 和 Edge 也接受 flex 高度。
Also, Chrome will accept flex-grow
as an adequate parent reference if used in conjunction with flex-basis
(any numerical value works (auto
won't), including flex-basis: 0
). As of this writing, however, this solution fails in Safari.
此外,如果与(任何数值有效(不会),包括)结合使用,Chrome 将接受flex-grow
作为足够的父引用。然而,在撰写本文时,此解决方案在 Safari 中失败。flex-basis
auto
flex-basis: 0
#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>
Four Solutions
四种解决方案
1. Specify a height on all parent elements
1. 指定所有父元素的高度
A reliable cross-browser solution is to specify a height on all parent elements. This prevents missing links, which Webkit-based browsers consider a violation of the spec.
一个可靠的跨浏览器解决方案是在所有父元素上指定高度。这可以防止丢失链接,基于 Webkit 的浏览器认为这些链接违反了规范。
Note that min-height
and max-height
are not acceptable. It must be the height
property.
请注意,min-height
和max-height
是不可接受的。必须是height
财产。
More details here: Working with the CSS height
property and percentage values
此处有更多详细信息: 使用 CSSheight
属性和百分比值
2. CSS Relative & Absolute Positioning
2. CSS 相对定位和绝对定位
Apply position: relative
to the parent and position: absolute
to the child.
适用position: relative
于父母和position: absolute
孩子。
Size the child with height: 100%
and width: 100%
, or use the offset properties: top: 0
, right: 0
, bottom: 0
, left: 0
.
使用height: 100%
和调整子级大小width: 100%
,或使用偏移属性:top: 0
、right: 0
、bottom: 0
、left: 0
。
With absolute positioning, percentage height works without a specified height on the parent.
使用绝对定位,百分比高度在父级上没有指定高度的情况下工作。
3. Remove unnecessary HTML containers (recommended)
3.删除不必要的HTML容器(推荐)
Is there a need for two containers around button
? Why not remove .item
or .item-inner
, or both? Although button
elements sometimes fail as flex containers, they can be flex items. Consider making button
a child of .container
or .item
, and removing gratuitous mark-up.
周围需要两个容器button
吗?为什么不删除.item
或.item-inner
,或两者兼而有之?尽管button
元素有时不能作为弹性容器,但它们可以是弹性项目。考虑创建或button
的子项,并删除无偿标记。.container
.item
Here's an example:
下面是一个例子:
.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. Nested Flex Containers (recommended)
4. 嵌套 Flex 容器(推荐)
Get rid of percentage heights. Get rid of table properties. Get rid of vertical-align
. Avoid absolute positioning. Just stick with flexbox all the way through.
摆脱百分比高度。摆脱表格属性。摆脱vertical-align
. 避免绝对定位。一直坚持使用 flexbox。
Apply display: flex
to the flex item (.item
), making it a flex container. This automatically sets align-items: stretch
, which tells the child (.item-inner
) to expand the full height of the parent.
应用于display: flex
弹性项目 ( .item
),使其成为弹性容器。这会自动设置align-items: stretch
,它告诉子.item-inner
节点( ) 扩展父节点的整个高度。
Important: Remove specified heights from flex items for this method to work.If a child has a height specified (e.g. height: 100%
), then it will ignore the align-items: stretch
coming from the parent. For the stretch
default to work, the child's height must compute to auto
(full explanation).
重要提示:从 flex 项目中删除指定的高度以使此方法起作用。如果孩子有指定的高度(例如height: 100%
),那么它将忽略align-items: stretch
来自父母的身高。对于stretch
默认的工作,孩子的身高必须计算到auto
(充分的解释)。
Try this (no changes to HTML):
试试这个(对 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
js小提琴
回答by nghiepit
Solution: Remove height: 100%
in .item-innerand add display: flex
in .item
解决方法:height: 100%
在.item-inner 中删除并display: flex
在.item 中添加
回答by huseyin39
Specifying a flex attribute to the container worked for me:
为容器指定 flex 属性对我有用:
.container {
flex: 0 0 auto;
}
This ensures the height is set and doesn't grow either.
这可确保高度已设置并且也不会增长。
回答by Narasinghe
For Mobile Safari There is a Browser fix. you need to add -webkit-boxfor iOS devices.
对于 Mobile 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;
if you're using align-items: stretch;
property for parent element, remove the height : 100%
from the child element.
如果您使用align-items: stretch;
父元素的属性,请height : 100%
从子元素中删除。
回答by Designer023
I have had a similar issue in iOS 8, 9 and 10 and the info above couldn't fix it, however I did discover a solution after a day of working on this. Granted it won't work for everyone but in my case my items were stacked in a column and had 0 height when it should have been content height. Switching the css to be row and wrap fixed the issue. This only works if you have a single item and they are stacked but since it took me a day to find this out I thought I should share my fix!
我在 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%;
}
回答by Carlton Lindsay
I had a similar bug, but while using a fixed number for height and not a percentage. It was also a flex container within the body (which has no specified height). It appeared that on Safari, my flex container had a height of 9px for some reason, but in all other browsers it displayed the correct 100px height specified in the stylesheet.
我有一个类似的错误,但是使用固定的高度而不是百分比。它也是主体内的一个 flex 容器(没有指定的高度)。似乎在 Safari 上,由于某种原因,我的 flex 容器的高度为 9px,但在所有其他浏览器中,它显示了样式表中指定的正确 100px 高度。
I managed to get it to work by adding both the height
and min-height
properties to the CSS class.
我设法通过将height
和min-height
属性添加到 CSS 类来使其工作。
The following worked for me on both Safari 13.0.4 and Chrome 79.0.3945.130:
以下内容在 Safari 13.0.4 和 Chrome 79.0.3945.130 上都对我有用:
.flex-container {
display: flex;
flex-direction: column;
min-height: 100px;
height: 100px;
}
Hope this helps!
希望这可以帮助!