web-dev-qa-db-fra.com

L'élément flex parfaitement positionné n'est pas supprimé du flux normal dans IE11

Nous avons deux divs avec contenu et un troisième div est un fond avec position absolue.

Le conteneur est une boîte flexible.

Tout fonctionne bien dans Chrome et Safari, mais Firefox et IE11 prend en compte le div positionné en absolu et distribue l'espace entre les divs comme s'il y avait 3 divs dans une rangée.

 enter image description here

J'ai fait exemple par exemple. Existe-t-il un moyen de résoudre ce problème? 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

Cela se produit parce que justify-content: space-between; distribue les éléments de manière uniforme. Le premier élément au début, le dernier à la fin. Il suffit donc de mettre <div class="bg">Background</div> entre <div class="c1">Content 1</div> et <div class="c2">Content 2</div> comme ça 

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

</div>

Vous pouvez voir le motif sur https://developer.mozilla.org/en-US/docs/Web/CSS/justify-content

13
Guru

UPDATE: Ce problème a été résolu dans Firefox (à partir de v52, publié en mars 2017). Le problème existe toujours dans IE11.


Comme vous l'avez écrit dans la question:

Firefox calcule la position absolue div et distribue l’espace entre les divs comme il y en a 3 à la suite.

Firefox envisage la troisième div (.bg), qui est positionnée de manière absolue, un élément entrant flex et le factorisant dans son calcul space-between. (IE11 le fait aussi; Chrome et Edge l'ignorent.)

Clairement, cela n’est pas conforme à la spécification actuelle de la flexbox:

4.1. Enfants Flex Absolument-Positionnés

Comme il est hors du flux, un enfant d'un flex absolu conteneur ne participe pas à la mise en page flex.

Voici quelques solutions de contournement:

Pourquoi ne pas déplacer le div positionné absolument entre les deux autres?

Au lieu de cela:

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

Essaye ça:

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

OU ... supprimez .bg du conteneur flex:

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

OU ... utilisez la propriété flex order pour réorganiser les éléments flex.

Ajoutez ceci à votre code:

.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

Parfois, il n'est pas possible de commander à nouveau des éléments, par exemple avec ::before et ::after. Dans ces cas, vous pouvez manuellement order les éléments.

Dans votre cas, vous devez faire:

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

La propriété order fait partie de la spécification flex et vous permet de réorganiser des éléments flexibles ( référence sur MDN ). C'est très pratique pour de multiples objectifs, y compris.

J'ai utilisé -1 parce que la valeur est ordinale. Par conséquent, le définir sur un nombre négatif garantit qu'il précède tous les autres paramètres par défaut et vous n'avez pas besoin de spécifier la valeur pour ::before. Pour la même raison, l'utilisation de 10 garantit que la deuxième division est la dernière, même si vous ajoutez un tas d'éléments au conteneur. Vous pouvez l'augmenter à 100 ou à un autre moment.

Néanmoins, le comportement de Firefox semble contre-intuitif. position: absolute supprime normalement l'élément du flux dom habituel et je m'attendrais à ce que cet élément soit également supprimé du flux flex, tout comme dans Safari et Chrome. Je ne suis pas sûr que les spécifications clarifient cela.

5

Vous pouvez également utiliser la propriété flex dans le ou les sélecteurs de contenu:

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

      flex: 1; /* add this */
    }

Cela définira le flex-grow. Ce n'est peut-être pas exactement ce dont vous avez besoin, mais cela peut peut-être aider quelqu'un d'autre qui ne peut pas réorganiser les divs de contenu ni les extraire de l'emballage flexible.

Voici la démo: https://jsfiddle.net/s18do03e/14/

0
Constantin Stan