【问题标题】:Chrome / Safari not filling 100% height of flex parentChrome / Safari 未填充 flex 父级的 100% 高度
【发布时间】:2016-02-11 17:34:27
【问题描述】:

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

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

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

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

为了使文本与中间对齐,我使用了display: table-cell 技术。但是使用表格显示需要使用 100% 的高度。

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

  1. 是否有解决此问题的方法?
  2. 或者是否有其他技术可以使所有.item 填充父级的高度,并使文本垂直对齐到中间?

Example here jsFiddle, should be viewed in Firefox and 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>

【问题讨论】:

标签: css google-chrome webkit flexbox


【解决方案1】:

解决方案

使用嵌套的弹性容器。

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

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

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

试试这个(不更改 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 (Chrome)。

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

10.5 Content height: the height property

百分比
指定百分比高度。百分比是根据生成框的高度计算的 包含块。如果包含块的高度不是 明确指定并且该元素不是绝对定位的,则该值计算为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-basis 结合使用,Chrome 将接受 flex-grow 作为足够的父引用(任何数值都有效(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>

四种解决方案

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 {
    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 容器(推荐)

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

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

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

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

【讨论】:

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

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

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

【讨论】:

  • 谢谢,这对我有帮助。 flex 孩子会自动拉伸到容器的高度吗?这就是它起作用的原因吗?
  • @ReeceKenney,是的,你的问题。这在我的回答中得到了解释。请参阅解决方案 #4。
【解决方案3】:

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

【讨论】:

    【解决方案4】:

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

    【讨论】:

    • omg 非常感谢你让我免于头痛! display: -webkit-box; 正是我所需要的。事实证明,即使在 2020 年末,iOS 设备仍然没有可预测的 flex 支持
    【解决方案5】:

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

    .container {
        flex: 0 0 auto;
    }
    

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

    【讨论】:

    • 帮我修好了!真是救命稻草。
    • 我非常希望它能够工作,但我最终将容器从视口底部移开
    • 为我工作。太感谢了。在此之前不明白为什么重定向到另一个页面时我的高度在 safari 上只有 1px。
    猜你喜欢
    • 2021-06-21
    相关资源
    最近更新 更多