it-swarm.com.ru

Абсолютно позиционированный элемент Flex не удаляется из нормального потока в IE11

У нас есть два div с содержимым и третий div, который является фоном с абсолютной позицией.

Контейнер представляет собой флексбокс.

Все отлично работает в Chrome и Safari, но Firefox и IE11 учитывает абсолютный позиционированный элемент div и распределяет пространство между элементами div, как если бы в строке было 3 элемента div.

 enter image description here

Я сделал пример 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>

27
Nikolay Aleshkovskiy

Это происходит потому, что justify-content: space-between; равномерно распределяет предметы Первый элемент в начале, последний в конце. Так что просто вставьте <div class="bg">Background</div> между <div class="c1">Content 1</div> и <div class="c2">Content 2</div> как это 

<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

13
Guru

ОБНОВЛЕНИЕ: Эта проблема была решена в Firefox (начиная с версии v52, выпущенной в марте 2017 года). Проблема все еще существует в IE11.


Как вы написали в вопросе:

Firefox вычисляет абсолютный позиционный элемент div и распределяет пространство между элементами div, как если бы в строке было 3 элемента div.

Firefox рассматривает третий div (.bg), который является абсолютно позиционированным, in-flow flex-элементом и учитывает его в расчете space-between. (IE11 делает это тоже; Chrome и Edge игнорируют это.)

Понятно, что это не соответствует текущей спецификации flexbox:

4.1. Абсолютно позиционированные гибкие дети

Поскольку это вне потока, абсолютно позиционированный потомок 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>

ИЛИ ... удалить .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>

32
Michael_B

Иногда невозможно переупорядочить материал, например, при использовании ::before и ::after. В этих случаях вы можете вручную order элементы.

В вашем случае вам нужно будет сделать:

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

Свойство order является частью спецификации flex и позволяет вам переупорядочивать flex-элементы ( ссылка на MDN ). Это очень удобно для нескольких целей, в том числе.

Я использовал -1, потому что значение является порядковым, поэтому установка его в отрицательное число гарантирует, что он предшествует всем другим значениям по умолчанию, и вам не нужно указывать значение для ::before. По той же причине использование 10 гарантирует, что второй div будет последним, даже если вы добавите несколько элементов в контейнер. Вы можете увеличить это до 100 или как угодно.

Тем не менее, поведение Firefox кажется нелогичным. position: absolute обычно удаляет элемент для обычного потока dom, и я ожидаю, что этот элемент также будет удален из потока flex, как в Safari и Chrome. Я не уверен, что спецификация проясняет это.

5
Emanuele Feliziani

В качестве альтернативы вы можете использовать свойство flex внутри селектора контента:

    div.c1 {
      background: #aaeecc;
      width: 100px;
      position: relative;
      z-index: 50; top: 20px;
      display: flex;

      flex: 1; /* add this */
    }

Это установит flex-grow. Это может быть не совсем то, что вам нужно, но, возможно, это поможет кому-то еще, кто не может переупорядочить элементы содержимого или извлечь их из оболочки Flex.

Вот демо: https://jsfiddle.net/s18do03e/14/

0
Constantin Stan