Comment puis-je faire en sorte que les enfants Flexbox atteignent 100% de la hauteur de leurs parents?

459

J'essaie de remplir l'espace vertical d'un élément flexible à l'intérieur d'une Flexbox.

.container {
  height: 200px;
  width: 500px;
  display: flex;
  flex-direction: row;
}
.flex-1 {
  width: 100px;
  background-color: blue;
}
.flex-2 {
  position: relative;
  flex: 1;
  background-color: red;
}
.flex-2-child {
  height: 100%;
  width: 100%;
  background-color: green;
}
<div class="container">
  <div class="flex-1"></div>
  <div class="flex-2">
    <div class="flex-2-child"></div>
  </div>
</div>

Et voici le JSFiddle

flex-2-child ne remplit pas la hauteur requise sauf dans les deux cas où:

  1. flex-2 a une hauteur de 100% (ce qui est bizarre car un élément flexible a 100% par défaut + il est buggé dans Chrome)
  2. flex-2-child a une position absolue qui est également gênante

Cela ne fonctionne pas actuellement dans Chrome ou Firefox.

Raz
la source
quel est le problème avec l'utilisation de la hauteur: 100%; pour .flex-2?
rmagnum2002
Il défie le but de l'élément flexible qui est de remplir le contenu lui-même et cela me donne le bug le plus étrange en chrome où la hauteur revient à zéro chaque fois que je redimensionne la fenêtre
Raz
3
En fait, la dernière version de Firefox est la seule qui fonctionne correctement
Raz
1
Actuellement, il existe des différences de comportement importantes entre les navigateurs en ce qui concerne le rendu des hauteurs de pourcentage dans flexbox: stackoverflow.com/a/35537510/3597276
Michael Benjamin
2
Oui, Chrome a quelques problèmes, en particulier avec les flexbox imbriquées. Par exemple, j'ai une boîte flexible imbriquée avec des enfants qui en ont height:100%mais qui sont rendus à la hauteur naturelle à la place. Et le plus étrange, c'est que si je change leur hauteur en auto, ils restituent comme height:100%j'essayais de le faire. Ce n'est certainement pas intuitif si c'est ainsi que cela devrait fonctionner.
trusktr

Réponses:

238

Utilisation align-items: stretch

Semblable à la réponse de David Storey, ma solution est la suivante:

.flex-2 {
    display: flex;
    align-items: stretch;
}

Vous align-itemspouvez également utiliser align-selfuniquement l' .flex-2-childélément que vous souhaitez étirer.

BT
la source
7
stretch: ce devrait être la réponse choisie.
Dave Everitt
1
Certainement, c'est de loin la meilleure réponse à la question. Marche parfaitement.
marcias
Oui, c'est en effet la meilleure réponse à cette question.
Øyvind Bråthen
20
n'oubliez pas de supprimer également height: 100%du composant enfant que vous souhaitez avoir la même taille que le parent
Ilham Wahabi GX
Veuillez ajouter la suppression height: 100%à la réponse - j'ai failli abandonner et je n'ai vu cela qu'au dernier moment avant de revenir à absolute- ce qui pose toutes sortes de problèmes.
Peter
274

J'ai répondu à une question similaire ici .

Je sais que vous avez déjà dit que ce position: absolute;n'était pas pratique, mais cela fonctionne. Voir ci-dessous pour plus d'informations sur la résolution du problème de redimensionnement.

Voir aussi ce jsFiddle pour une démo, même si je n'ai ajouté que des préfixes webkit donc ouverts dans Chrome.

Vous avez essentiellement 2 problèmes que je traiterai séparément.

  1. Faire en sorte que l'enfant d'un élément flexible remplisse la hauteur à 100%
    • Fixez position: relative;sur le parent de l'enfant.
    • Montez position: absolute;sur l'enfant.
    • Vous pouvez ensuite définir la largeur / hauteur selon vos besoins (100% dans mon échantillon).
  2. Correction du "redimensionnement" du défilement de redimensionnement dans Chrome
    • Mettez overflow-y: auto;le div défilable.
    • Le div scrollable doit avoir une hauteur explicite spécifiée. Mon échantillon a déjà une hauteur de 100% mais si aucun n'est déjà appliqué, vous pouvez spécifierheight: 0;

Consultez cette réponse pour plus d'informations sur le problème de défilement.

Brett Postin
la source
10
Point 1) fonctionne parfaitement dans Chrome, Firefox n'a pas besoin de la position absolue.
yuri
224

Si je comprends bien, vous voulez que flex-2-child remplisse la hauteur et la largeur de son parent, de sorte que la zone rouge soit entièrement couverte par le vert?

Si c'est le cas, il vous suffit de configurer flex-2 pour utiliser flexbox:

.flex-2 {
    display: flex;  
}

Dites ensuite à flex-2-child de devenir flexible:

.flex-2-child {    
    flex: 1;
}

Voir http://jsfiddle.net/2ZDuE/10/

La raison en est que flex-2-child n'est pas un élément flexbox, mais son parent l'est.

David Storey
la source
Comment puis-je faire de même, juste avec une hauteur de 100% et chaque enfant a 50/50?
Ricky Levi
7
Sachez que si vous utilisez "align-items: center", vous ne pourrez pas utiliser ce correctif car vos éléments deviendront désormais de hauteur égale.
Neil Monroe
10
@NeilMonroe Vous pouvez toujours utiliser align-items: centersi vous utilisez align-self: stretchsur un seul enfant.
BT
1
Salut @David, j'ai essayé votre solution, cela fonctionne bien pour la flex-direction: disposition des lignes, il ne semble pas fonctionner avec flex-direction: la disposition des colonnes, ou j'ai des erreurs dans le code. Pourriez-vous aider à vérifier pourquoi dans ce violon jsfiddle.net/78o54Lmv , la boîte intérieure n'occupera pas toute la hauteur de son parent?
huan feng
Je dois ajouter min-height: 100vh;à l' .flex-2élément pour que cela fonctionne. Merci pour l'aide!
Tenaciousd93
24

Je suppose que le comportement de Chrome est plus cohérent avec la spécification CSS (bien qu'il soit moins intuitif). Selon la spécification Flexbox, la stretchvaleur par défaut de la align-selfpropriété modifie uniquement la valeur utilisée de la "propriété de taille croisée" de l'élément ( height, dans ce cas). Et, si je comprends bien la spécification CSS2.1 , les hauteurs en pourcentage sont calculées à partir de la valeur spécifiée du parent height, et non de sa valeur utilisée. La valeur spécifiée du parent heightn'est affectée par aucune propriété de flexion et l'est toujours auto.

La définition explicite height: 100%permet formellement de calculer le pourcentage de hauteur de l'enfant, tout comme la définition height: 100%de htmlpermet de calculer la hauteur en pourcentage de bodyCSS2.1.

Ilya Streltsyn
la source
2
Exactement! Pour mettre cela en pratique, il suffit d'ajouter height:100%à .flex-2. Voici le jsfiddle .
CourtDemone
7
Le comportement de Chrome est plus cohérent avec l'interprétation par Chrome Team de la spécification CSS. Bien qu'il puisse être interprété de cette façon, il existe de bien meilleures façons de l'interpréter, dont aucune ne nous aurait piégés dans ce bazar, un comportement ennuyeux et ennuyeux. Ils auraient dû y réfléchir davantage.
WraithKenny
1
@RickDoesburg, c'était il y a plus d'un an, mais je crois que j'ai dû recourir à des éléments à hauteur fixe. Je souhaite que ces navigateurs se mettent ensemble. Je commence vraiment à détester l'espace mobile.
Jordan
1
Définir un enfant d'un conteneur Flexbox vertical height: 100%donne des résultats très étranges pour moi dans Chrome. Il semble que cela entraîne la définition de la "hauteur spécifiée" à la hauteur totale du conteneur , plutôt qu'à la hauteur de l'élément lui-même, ce qui provoque un défilement indésirable lorsque d'autres éléments ont des tailles calculées par rapport à lui.
Jules
13

J'ai trouvé la solution par moi-même, supposons que vous ayez le CSS ci-dessous:

.parent {
  align-items: center;
  display: flex;
  justify-content: center;
}

.child {
  height: 100%; <- didn't work
}

Dans ce cas, la définition de la hauteur à 100% ne fonctionnera pas, donc ce que je fais est de définir la margin-bottomrègle auto, comme:

.child {
  margin-bottom: auto;
}

et l'enfant sera aligné au sommet du parent, vous pouvez également utiliser la align-selfrègle de toute façon si vous préférez.

.child {
  align-self: flex-start;
}
user3896501
la source
Un bon hack, mais le problème est: si l'enfant est une barre latérale et qu'il a une couleur de fond, l'espace de marge est toujours blanc.
Boris Burkov
Ce qui est génial avec cette solution, c'est que la hauteur du parent peut être dynamique! Les solutions précédentes exigent que le parent ait une hauteur définie. Merci pour cela.
Bribbons
4

Une idée serait que display:flex;avec flex-direction: row;remplisse le containerdiv avec .flex-1et .flex-2, mais cela ne signifie pas qu'il .flex-2a une valeur par défaut height:100%;même s'il est étendu à pleine hauteur et d'avoir un élément enfant ( .flex-2-child) avec height:100%;vous devrez définir le parent sur height:100%;ou utiliser display:flex;avec flex-direction: row;sur le .flex-2div aussi.

D'après ce que je sais display:flex, la hauteur de tous vos éléments enfants ne sera pas étendue à 100%.

Une petite démo, supprimée de la hauteur .flex-2-childet utilisée display:flex;sur .flex-2: http://jsfiddle.net/2ZDuE/3/

rmagnum2002
la source
3

html

<div class="container">
    <div class="flex-1"></div>
    <div class="flex-2">
        <div class="flex-2-child"></div>
    </div>
</div>

css

.container {
    height: 200px;
    width: 500px;
    display: -moz-box;
    display: -webkit-flexbox;
    display: -ms-flexbox;
    display: -webkit-flex;
    display: -moz-flex;
    display: flex;
    -webkit-flex-direction: row;
    -moz-flex-direction: row;
    -ms-flex-direction: row;
    flex-direction: row;
}
.flex-1 {
   flex:1 0 100px;
    background-color: blue;
}
.flex-2 {
    -moz-box-flex: 1;
    -webkit-flex: 1;
    -moz-flex: 1;
    -ms-flex: 1;
    flex: 1 0 100%;
    background-color: red;
}
.flex-2-child {
    flex: 1 0 100%;
    height:100%;
    background-color: green;
}

http://jsfiddle.net/2ZDuE/750/

Carol McKay
la source
0

Cela peut également être résolu avec align-self: stretch;l'élément que nous voulons étirer.

Parfois, il est souhaitable d'étirer un seul élément dans une configuration flexbox.

.container {
  height: 200px;
  width: 500px;
  display: flex;
  flex-direction: row;
}
.flex-1 {
  width: 100px;
  background-color: blue;
}
.flex-2 {
  position: relative;
  flex: 1;
  align-self: stretch;
  background-color: red;
}
.flex-2-child {
  background-color: green;
}
<div class="container">
  <div class="flex-1"></div>
  <div class="flex-2">
    <div class="flex-2-child"></div>
  </div>
</div>

GiorgosK
la source
-7

.récipient { . . . . align-items: étirer; . . . . }

HRK
la source
5
Bienvenue sur stackoverflow. Vous devez expliquer pleinement votre réponse et ce qu'elle apporte de différent des réponses existantes. Voir stackoverflow.com/help/how-to-answer
Simon.SA
1
Votre réponse semble être la même que celle de BT (écrite plus de trois ans plus tôt) mais exprimée beaucoup plus mal.
Quentin
-12

Ceci est ma solution en utilisant css +

Tout d'abord si le premier enfant (flex-1) doit être 100px ne doit pas être flex. Dans css +, en fait, vous pouvez définir des éléments flexibles et / ou statiques (colonnes ou lignes) et votre exemple devient aussi simple que cela:

<div class="container">
  <div class="EXTENDER">
    <div class="COLS">
      <div class="CELL _100px" style="background-color:blue">100px</div>
      <div class="CELL _FLEX" style="background-color:red">flex</div>
    </div>
  </div>
</div>

conteneur css:

.container {
    height: 200px;
    width: 500px;
    position:relative;
}

et incluent évidemment css + 0.2 core

entendre le violon

Marco Allori
la source