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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 11:34:40  来源:igfitidea点击:

Chrome / Safari not filling 100% height of flex parent

cssgoogle-chromewebkitflexbox

提问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 .containercontains 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-celltechnique. 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) 中不起作用。

  1. Is there a fix for this problem?
  2. Or is there a different technique to make all .itemfill the height of the parent with text vertical aligned to middle?
  1. 这个问题有解决办法吗?
  2. 或者是否有一种不同的技术可以使.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: flexto 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: stretchcoming from the parent. For the stretchdefault 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 demo

jsFiddle 演示



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 heightproperty

percentage
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 to auto.

auto
The height depends on the values of other properties.

10.5 内容高度:height属性

百分比
指定百分比高度。该百分比是根据生成的框的包含块的高度计算的。如果未明确指定包含块的高度并且此元素不是绝对定位,则该值计算为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 – .itemdoes nothave a defined height. Webkit sees that as a missing link.

但它们之间,二级容器.item————并没有明确的高度。Webkit 认为这是一个缺失的环节。

.item-inneris 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: 1rule 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-growas an adequate parent reference if used in conjunction with flex-basis(any numerical value works (autowon't), including flex-basis: 0). As of this writing, however, this solution fails in Safari.

此外,如果与(任何数值有效(不会),包括)结合使用,Chrome 将接受flex-grow作为足够的父引用。然而,在撰写本文时,此解决方案在 Safari 中失败。flex-basisautoflex-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-heightand max-heightare not acceptable. It must be the heightproperty.

请注意,min-heightmax-height是不可接受的。必须是height财产。

More details here: Working with the CSS heightproperty and percentage values

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

2. CSS Relative & Absolute Positioning

2. CSS 相对定位和绝对定位

Apply position: relativeto the parent and position: absoluteto 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: 0right: 0bottom: 0left: 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 .itemor .item-inner, or both? Although buttonelements sometimes fail as flex containers, they can be flex items. Consider making buttona child of .containeror .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: flexto 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: stretchcoming from the parent. For the stretchdefault 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: flexin .item

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

Demo: https://codepen.io/tronghiep92/pen/NvzVoo

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

回答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 heightand min-heightproperties to the CSS class.

我设法通过将heightmin-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!

希望这可以帮助!