绝对定位的弹性项目不会从 IE11 中的正常流程中删除

Posted

技术标签:

【中文标题】绝对定位的弹性项目不会从 IE11 中的正常流程中删除【英文标题】:Absolutely positioned flex item is not removed from the normal flow in 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>

【问题讨论】:

截至 12 月的 flex-container 内的绝对定位。 2019:codepen.io/ekadagami/pen/mdyPybq 【参考方案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/

【讨论】:

以上是关于绝对定位的弹性项目不会从 IE11 中的正常流程中删除的主要内容,如果未能解决你的问题,请参考以下文章

弹性容器中的文本不会在 IE11 中换行

具有绝对位置的 Flexbox 容器不适合 IE 中的内容宽度

IE11上表格单元格内绝对位置的奇怪行为

IE 11、Flexbox 和绝对定位不起作用

绝对底部定位在 Edge 和 IE 中未按预期工作

flex 容器中的绝对定位项仍被视为 IE 和 Firefox 中的项