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

Ric*_*eda 204 css webkit google-chrome css3 flexbox

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

每个孩子必须填写父母的高度并且具有中间对齐的文本.

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

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

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

我的问题是.item-inner { height: 100% }在webkit(Chrome)中无效.

  1. 这个问题有解决方法吗?
  2. 或者是否有一种不同的技术可以使所有.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;
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

Mic*_*l_B 360

使用嵌套的Flex容器.

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

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

重要说明:从弹性项中删除指定的高度,以使此方法起作用.如果孩子指定了一个身高(例如height: 100%),那么它将忽略align-items: stretch来自父亲的身高.要使stretch默认设置起作用,子项的高度必须计算为auto (完整说明).

试试这个(不修改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 */
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

jsFiddle演示


说明

我的问题是.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也接受弹性高度.

此外,如果与(任何数值工作(不会),包括)一起使用,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;
}
Run Code Online (Sandbox Code Playgroud)
<div id="outer">
  <div id="middle">
    <div id="inner">
      INNER
    </div>
  </div>
</div>
Run Code Online (Sandbox Code Playgroud)


四解决方案

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

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

需要注意的是min-heightmax-height是不能接受的.它必须是height财产.

更多详细信息: 使用CSS height属性和百分比值

2. CSS相对和绝对定位

适用position: relative于父母和position: absolute孩子.

大小的孩子height: 100%width: 100%,或使用污损特性:top: 0,right: 0,bottom: 0,left: 0.

使用绝对定位时,百分比高度在父级上没有指定高度的情况下工作.

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

是否需要两个容器button?为什么不删除.item.item-inner,或两者兼而有之?尽管button元素有时会作为柔性容器失效,但它们可以是柔性物品.考虑让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 */
}
Run Code Online (Sandbox Code Playgroud)
<div class="container">
    <a>Button</a>
    <a>Button</a>
    <a>Button</a>
</div>
Run Code Online (Sandbox Code Playgroud)

4.嵌套的Flex容器(推荐)

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

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

重要说明:从弹性项中删除指定的高度,以使此方法起作用.如果孩子指定了一个身高(例如height: 100%),那么它将忽略align-items: stretch来自父亲的身高.要使stretch默认设置起作用,子项的高度必须计算为auto (完整说明).

试试这个(不修改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 */
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

的jsfiddle

  • 我可以确认使用嵌套flex容器效果最好。我们在菜单中不一致地使用了flexbox。代替在父容器上使用flex:1和display:flex,我们在某些地方使用height:100%。替换了相应的定义后,一切都按预期进行。感谢@Michael_B的提示!:) (3认同)
  • 我使用height:auto解决了我的问题 (2认同)
  • @JamesHarrington,CSS 随着时间的推移而增长并且*复杂*;-) (2认同)

hus*_*n39 36

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

.container {
    flex: 0 0 auto;
}
Run Code Online (Sandbox Code Playgroud)

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

  • 帮我修好了!真是救星啊。 (2认同)

ngh*_*pit 11

解决方案:删除height: 100%.item-内,并添加display: flex.item

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


小智 9

对于 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;
Run Code Online (Sandbox Code Playgroud)

如果您使用align-items: stretch;父元素的属性,请height : 100%从子元素中删除。