【问题标题】:Absolutely positioned flex item is not removed from the normal flow in IE11绝对定位的弹性项目不会从 IE11 中的正常流程中删除
【发布时间】:2016-01-04 14:46:08
【问题描述】:

我们有两个带有内容的 div 和第三个带有绝对位置的背景的 div。

容器是一个弹性盒子。

在 Chrome 和 Safari 中一切正常,但 Firefox 和 IE11 会考虑绝对定位的 div,并在 div 之间分配空间,就像连续 3 个 div 一样。

我制作了 jsfiddle 示例。有没有办法修复这个错误? https://jsfiddle.net/s18do03e/2/

div.container {
  display: flex;
  flex-direction: row;
  width: 100%;
  height: 300px;
  justify-content: space-between;
  width: 100%;
  outline: 1px solid;
}
div.c1 {
  background: #aaeecc;
  width: 100px;
  position: relative;
  z-index: 50;
  top: 20px;
  display: flex;
}
div.c2 {
  background: #cceeaa;
  width: 200px;
  position: relative;
  z-index: 50;
  top: 20px;
  display: flex;
}
div.bg {
  background: #ccc;
  width: 100%;
  height: 100%;
  z-index: 0;
  left: 0px;
  top: 0px;
  position: absolute;
  display: flex;
}
<div class="container">
  <div class="c1">Content 1</div>
  <div class="c2">Content 2</div>
  <div class="bg">Background</div>
</div>

【问题讨论】:

标签: html css flexbox internet-explorer-11


【解决方案1】:

更新:此问题已在 Firefox 中得到解决(截至 2017 年 3 月发布的 v52)。 IE11问题依然存在。


就像你在问题中写的:

Firefox 计算绝对定位的 div,并在 div 之间分配空间,就像连续 3 个 div 一样。

Firefox 正在考虑第三个 div (.bg),它是绝对定位的,一个 in-flow flex 项目,并将其考虑到它的 space-between 计算中。 (IE11 也这样做;Chrome 和 Edge 忽略它。)

显然,这不符合当前的 flexbox 规范:

4.1. Absolutely-Positioned Flex Children

由于它是外流的,因此是 flex 的绝对定位子代 容器不参与弹性布局。

以下是一些解决方法:

为什么不在另外两个之间移动绝对定位的 div?

而不是这个:

<div class="container">
    <div class="c1">Content 1</div>
    <div class="c2">Content 2</div>
    <div class="bg">Background</div>
</div>

试试这个:

<div class="container">
    <div class="c1">Content 1</div>
    <div class="bg">Background</div>
    <div class="c2">Content 2</div>
</div>

div.container {
  display: flex;
  flex-direction: row;
  width: 100%;
  height: 300px;
  justify-content: space-between;
  width: 100%;
  outline: 1px solid;
}
div.c1 {
  background: #aaeecc;
  width: 100px;
  position: relative;
  z-index: 50;
  top: 20px;
  display: flex;
}
div.c2 {
  background: #cceeaa;
  width: 200px;
  position: relative;
  z-index: 50;
  top: 20px;
  display: flex;
}
div.bg {
  background: #ccc;
  width: 100%;
  height: 100%;
  z-index: 0;
  left: 0px;
  top: 0px;
  position: absolute;
  display: flex;
}
<div class="container">
  <div class="c1">Content 1</div>
  <div class="bg">Background</div>
  <div class="c2">Content 2</div>
</div>

或者...从 flex 容器中删除 .bg

<div class="container">
    <div class="c1">Content 1</div>
    <div class="c2">Content 2</div>
</div>
<div class="bg">Background</div>

div.container {
  display: flex;
  flex-direction: row;
  width: 100%;
  height: 300px;
  justify-content: space-between;
  width: 100%;
  outline: 1px solid;
}
div.c1 {
  background: #aaeecc;
  width: 100px;
  position: relative;
  z-index: 50;
  top: 20px;
  display: flex;
}
div.c2 {
  background: #cceeaa;
  width: 200px;
  position: relative;
  z-index: 50;
  top: 20px;
  display: flex;
}
div.bg {
  background: #ccc;
  width: 100%;
  height: 100%;
  z-index: 0;
  left: 0px;
  top: 0px;
  position: absolute;
  display: flex;
}
<div class="container">
  <div class="c1">Content 1</div>
  <div class="c2">Content 2</div>
</div>
<div class="bg">Background</div>

或者...使用 flex order 属性重新排列 flex 项。

将此添加到您的代码中:

.c2 { order: 1; }

div.container {
  display: flex;
  flex-direction: row;
  width: 100%;
  height: 300px;
  justify-content: space-between;
  width: 100%;
  outline: 1px solid;
}
div.c1 {
  background: #aaeecc;
  width: 100px;
  position: relative;
  z-index: 50;
  top: 20px;
  display: flex;
}
div.c2 {
  background: #cceeaa;
  width: 200px;
  position: relative;
  z-index: 50;
  top: 20px;
  display: flex;
  order: 1;
}
div.bg {
  background: #ccc;
  width: 100%;
  height: 100%;
  z-index: 0;
  left: 0px;
  top: 0px;
  position: absolute;
  display: flex;
}
<div class="container">
  <div class="c1">Content 1</div>
  <div class="c2">Content 2</div>
  <div class="bg">Background</div>
</div>

【讨论】:

  • 这是一个非常彻底的答案。看准队友。
  • 请注意,Firefox(和 IE)有这种行为,因为它是 required by an older revision of the flexbox spec —— abspos flex children 上的规范文本随着时间的推移发生了很大变化。不过好消息——Firefox 52 中的当前规范行为 will ship! (计划于 2017 年 3 月 7 日发布)
  • 干得好,最好的答案在这里。我建议在其他建议之前使用“order”属性,因为这确实是一个 CSS 问题,并且最后对背景 div 进行排序更好,并且可能无法将其从容器中删除。
  • order 到底在做什么?
  • 它将源中的第二个.c2元素移动到第三个位置(more info)。 @DrazenBjelovuk
【解决方案2】:

之所以发生,是因为justify-content: space-between; 均匀分布项目 第一个项目在开始,最后一个项目在结束。所以只需将&lt;div class="bg"&gt;Background&lt;/div&gt; 推入&lt;div class="c1"&gt;Content 1&lt;/div&gt;&lt;div class="c2"&gt;Content 2&lt;/div&gt; 之间 像这样

<div class="container">
    <div class="c1">Content 1</div>
    <div class="bg">Background</div>
    <div class="c2">Content 2</div>

</div>

你可以在https://developer.mozilla.org/en-US/docs/Web/CSS/justify-content看到原因

【讨论】:

    【解决方案3】:

    有时无法重新订购商品,例如使用::before::after 时。在这些情况下,您可以手动order 元素。

    在你的情况下,你需要这样做:

    .c1 {
      order: -1;
    }
    .c2 {
      order: 10;
    }
    

    order 属性是 flex 规范的一部分,可让您重新排序弹性项目 (reference on MDN)。它非常方便用于多种用途,包括这一点。

    我使用-1,因为该值是序数,因此将其设置为负数可确保它优先于所有其他默认值,并且您无需为::before 指定值。出于同样的原因,使用10 可确保第二个 div 排在最后,即使您向容器中添加了一堆元素。您可以将其增加到 100 或其他任何值。

    不过,Firefox 的行为似乎违反直觉。 position: absolute 通常会删除通常 dom 流的元素,我希望该元素也会从 flex 流中删除,就像在 Safari 和 Chrome 中一样。我不确定规范是否澄清了这一点。

    【讨论】:

      【解决方案4】:

      作为替代方案,您可以在内容选择器中使用 flex 属性:

          div.c1 {
            background: #aaeecc;
            width: 100px;
            position: relative;
            z-index: 50; top: 20px;
            display: flex;
      
            flex: 1; /* add this */
          }
      

      这将设置 flex-grow。它可能不是您所需要的,但它可能会帮助其他无法重新排序内容 div 或将它们从 flex 包装器中取出的人。

      这里是演示: https://jsfiddle.net/s18do03e/14/

      【讨论】:

        猜你喜欢
        • 2020-06-16
        • 2017-06-21
        • 2015-06-04
        • 2018-03-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-06-09
        相关资源
        最近更新 更多