Élément flex absolument positionné n'est pas retiré du flux normal dans IE11
Nous avons deux divs avec le contenu et un troisième div qui est un arrière-plan avec la position absolue.
Le conteneur est une flexbox.
Tout fonctionne bien dans Chrome et Safari, mais Firefox et IE11 facteurs dans le div positionné absolu, et distribue l'espace entre divs comme il y a 3 divs dans une rangée.
J'ai fait un exemple jsfiddle. Est-il possible de résoudre ce problème bug? 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>
4 réponses
Cela se produit parce que justify-content: space-between;
distribuez uniformément les éléments le premier élément au début, le dernier à la fin. Donc, juste putt <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 la raison sur https://developer.mozilla.org/en-US/docs/Web/CSS/justify-content
Mise à jour: 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 div positionné absolu, et distribue l'espace entre divs comme il y a 3 divs dans une rangée.
Firefox considère le troisième div (.bg
), qui est absolument positionné, un élémentin-flow flex et l'affacturage dans son calcul space-between
. (IE11 le fait aussi; Chrome et Edge l'ignorent.)
De toute évidence, cela n'est pas conforme à la spécification flexbox actuelle:
4.1. Enfants Flex Absolument Positionnés
Comme il est hors-flux, un enfant absolument positionné d'un flex conteneur ne participe pas à la mise en page flex.
Voici quelques solutions de contournement:
pourquoi ne pas déplacer le div absolument positionné entre l'autre deux?
Au lieu de ceci:
<div class="container">
<div class="c1">Content 1</div>
<div class="c2">Content 2</div>
<div class="bg">Background</div>
</div>
, Essayez ceci:
<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... supprimer .bg
sur le 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>
Parfois, il N'est pas possible de réorganiser des choses, par exemple lorsque vous utilisez ::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 les éléments flex (référence sur MDN). Il est très pratique à des fins multiples, cela inclus.
J'ai utilisé -1
parce que la valeur est ordinale, donc le définir sur un nombre négatif garantit qu'il précède tout autres valeurs 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 div arrive en dernier même si vous ajoutez un tas d'éléments au conteneur. Vous pouvez augmenter cela à 100
ou autre.
Pourtant, le comportement de Firefox semble contre-intuitif. position: absolute
supprime normalement l'élément pour le 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 de savoir si le spec clarifiez ceci.
Comme alternative, vous pouvez utiliser la propriété flex dans le (s) sélecteur (s) 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 peut-être que cela aide quelqu'un d'autre qui ne peut pas réorganiser les divs de contenu ou les sortir du wrapper flex.
Voici la démo: https://jsfiddle.net/s18do03e/14/