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

2024-01-15

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

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

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

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

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

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

  1. 这个问题有解决办法吗?
  2. 或者是否有不同的技术来制作所有.item用垂直居中对齐的文本填充父级的高度?

这里的例子是 jsFiddle,应该在 Firefox 和 Chrome 中查看 http://jsfiddle.net/y8mboo2s/

.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>

Solution

使用嵌套的弹性容器。

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

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

重要提示:要使此方法起作用,请从弹性项目中删除指定的高度。如果孩子有指定的身高(例如height: 100%),那么它将忽略align-items: stretch来自父母。为了stretch默认工作,孩子的身高必须计算为auto (完整解释 https://stackoverflow.com/q/44878379/3597276).

试试这个(不改变 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 演示 http://jsfiddle.net/y8mboo2s/3/


解释

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

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

10.5 内容高度:height财产 http://www.w3.org/TR/CSS22/visudet.html#the-height-property

百分比
指定百分比高度。百分比是根据生成的框的高度计算的 包含块。如果包含块的高度不是 明确指定并且该元素不是绝对定位的,该值计算为auto.

auto
高度取决于其他属性的值。

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

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

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

但在它们之间,还有第二层容器——.itemdoes not有规定的高度。 Webkit 认为这是一个缺失的环节。

.item-inner正在告诉 Chrome:give me height: 100%。 Chrome 会向父级 (.item)供参考并回应:100% 什么?我什么也没看到(忽略flex: 1那里的规则)。结果,它适用height: auto(内容高度),符合规范。

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

此外,Chrome 将接受flex-grow作为充分的家长参考如果与一起使用flex-basis(任何数值都有效(auto https://stackoverflow.com/q/53870751/3597276不会),包括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-height and max-height是不可接受的。一定是height财产。

更多详细信息请参见此处:使用 CSSheight属性和百分比值 https://stackoverflow.com/a/31728799/3597276

2.CSS相对和绝对定位

Apply position: relative给家长和position: absolute给孩子。

给孩子定尺寸height: 100% and width: 100%,或使用偏移属性:top: 0, right: 0, bottom: 0, left: 0.

对于绝对定位,百分比高度无需在父级上指定高度即可工作。

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

周围需要两个集装箱吗button?为什么不删除.item or .item-inner, 或两者?虽然button元素有时会作为弹性容器失败 https://stackoverflow.com/q/35464067/3597276,它们可以是弹性项目。考虑制作button的孩子.container or .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 就可以了。

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

重要提示:要使此方法起作用,请从弹性项目中删除指定的高度。如果孩子有指定的身高(例如height: 100%),那么它将忽略align-items: stretch来自父母。为了stretch默认工作,孩子的身高必须计算为auto (完整解释 https://stackoverflow.com/q/44878379/3597276).

试试这个(不改变 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 http://jsfiddle.net/y8mboo2s/3/

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Chrome / Safari 未填充 Flex 父级的 100% 高度 的相关文章

随机推荐