Solution
Utilisez des conteneurs flex imbriqués.
Débarrassez-vous des hauteurs de pourcentage. Débarrassez-vous des propriétés de la table. Débarrassez-vous vertical-align
. Évitez le positionnement absolu. Restez avec Flexbox tout au long.
Appliquer display: flex
à l'élément flexible ( .item
), ce qui en fait un conteneur flexible. Cela définit automatiquement align-items: stretch
, qui indique à l'enfant ( .item-inner
) d'étendre la hauteur totale du parent.
Important: supprimez les hauteurs spécifiées des éléments flexibles pour que cette méthode fonctionne. Si un enfant a une hauteur spécifiée (par exemple height: 100%
), alors il ignorera la align-items: stretch
venue du parent. Pour que la stretch
valeur par défaut fonctionne, la taille de l'enfant doit être calculée à auto
(explication complète ).
Essayez ceci (pas de modification du HTML):
.container {
display: flex;
flex-direction: column;
height: 20em;
border: 5px solid black
}
.item {
display: flex; /* new; nested flex container */
flex: 1;
border-bottom: 1px solid white;
}
.item-inner {
display: flex; /* new; nested flex container */
flex: 1; /* new */
/* height: 100%; <-- remove; unnecessary */
/* width: 100%; <-- remove; unnecessary */
/* display: table; <-- remove; unnecessary */
}
a {
display: flex; /* new; nested flex container */
flex: 1; /* new */
align-items: center; /* new; vertically center text */
background: orange;
/* display: table-cell; <-- remove; unnecessary */
/* vertical-align: middle; <-- remove; unnecessary */
}
<div class="container">
<div class="item">
<div class="item-inner">
<a>Button</a>
</div>
</div>
<div class="item">
<div class="item-inner">
<a>Button</a>
</div>
</div>
<div class="item">
<div class="item-inner">
<a>Button</a>
</div>
</div>
</div>
Démo jsFiddle
Explication
Mon problème est que cela .item-inner { height: 100% }
ne fonctionne pas dans le webkit (Chrome).
Cela ne fonctionne pas car vous utilisez le pourcentage de hauteur d'une manière qui n'est pas conforme à l'implémentation traditionnelle de la spécification.
10.5 Hauteur du contenu: la height
propriété
pourcentage
Spécifie un pourcentage de hauteur. Le pourcentage est calculé par rapport à la hauteur du bloc contenant la boîte générée. Si la hauteur du bloc conteneur n'est pas spécifiée explicitement et que cet élément n'est pas positionné de manière absolue, la valeur est calculée en auto
.
auto
La hauteur dépend des valeurs des autres propriétés.
En d'autres termes, pour que le pourcentage de hauteur fonctionne sur un enfant entrant, le parent doit avoir une hauteur définie.
Dans votre code, le conteneur de niveau supérieur a une hauteur définie: .container { height: 20em; }
Le conteneur de troisième niveau a une hauteur définie: .item-inner { height: 100%; }
Mais entre eux, le conteneur de deuxième niveau - .item
- n'a pas de hauteur définie. Webkit voit cela comme un lien manquant.
.item-inner
dit à Chrome: donnez-moiheight: 100%
. Chrome regarde le parent ( .item
) pour référence et répond: 100% de quoi? Je ne vois rien (en ignorant la flex: 1
règle qui existe). En conséquence, il s'applique height: auto
(hauteur du contenu), conformément à la spécification.
Firefox, d'autre part, accepte désormais la hauteur de flexion d'un parent comme référence pour le pourcentage de taille de l'enfant. IE11 et Edge acceptent également les hauteurs flexibles.
En outre, Chrome acceptera flex-grow
comme référence parent adéquate s'il est utilisé en conjonction avecflex-basis
(toute valeur numérique fonctionne ( auto
ne le sera pas), y compris flex-basis: 0
). Cependant, à ce jour, cette solution échoue dans Safari.
#outer {
display: flex;
flex-direction: column;
height: 300px;
background-color: white;
border: 1px solid red;
}
#middle {
flex-grow: 1;
flex-basis: 1px;
background-color: yellow;
}
#inner {
height: 100%;
background-color: lightgreen;
}
<div id="outer">
<div id="middle">
<div id="inner">
INNER
</div>
</div>
</div>
Quatre solutions
1. Spécifiez une hauteur sur tous les éléments parents
Une solution multi-navigateur fiable consiste à spécifier une hauteur sur tous les éléments parents. Cela empêche les liens manquants, que les navigateurs Webkit considèrent comme une violation de la spécification.
Notez que min-height
et max-height
ne sont pas acceptables. Ce doit être la height
propriété.
Plus de détails ici: Utilisation de la height
propriété CSS et des valeurs de pourcentage
2. Positionnement relatif et absolu CSS
S'applique position: relative
au parent et position: absolute
à l'enfant.
Taille l'enfant height: 100%
et width: 100%
, ou utiliser les propriétés offset: top: 0
, right: 0
, bottom: 0
, left: 0
.
Avec un positionnement absolu, la hauteur en pourcentage fonctionne sans hauteur spécifiée sur le parent.
3. Supprimez les conteneurs HTML inutiles (recommandé)
Y a-t-il besoin de deux conteneurs autour button
? Pourquoi ne pas supprimer .item
ou .item-inner
, ou les deux? Bien que les button
éléments échouent parfois en tant que conteneurs flexibles , ils peuvent être des éléments flexibles. Envisagez de faire button
un enfant de .container
ou .item
et de supprimer la majoration gratuite.
Voici un exemple:
.container {
height: 20em;
display: flex;
flex-direction: column;
border: 5px solid black
}
a {
flex: 1;
background: orange;
border-bottom: 1px solid white;
display: flex; /* nested flex container (for aligning text) */
align-items: center; /* center text vertically */
justify-content: center; /* center text horizontally */
}
<div class="container">
<a>Button</a>
<a>Button</a>
<a>Button</a>
</div>
4. Conteneurs Flex imbriqués (recommandé)
Débarrassez-vous des hauteurs de pourcentage. Débarrassez-vous des propriétés de la table. Débarrassez-vous vertical-align
. Évitez le positionnement absolu. Restez avec Flexbox tout au long.
Appliquer display: flex
à l'élément flexible ( .item
), ce qui en fait un conteneur flexible. Cela définit automatiquement align-items: stretch
, qui indique à l'enfant ( .item-inner
) d'étendre la hauteur totale du parent.
Important: supprimez les hauteurs spécifiées des éléments flexibles pour que cette méthode fonctionne. Si un enfant a une hauteur spécifiée (par exemple height: 100%
), alors il ignorera la align-items: stretch
venue du parent. Pour que la stretch
valeur par défaut fonctionne, la taille de l'enfant doit être calculée à auto
(explication complète ).
Essayez ceci (pas de modification du HTML):
.container {
display: flex;
flex-direction: column;
height: 20em;
border: 5px solid black
}
.item {
display: flex; /* new; nested flex container */
flex: 1;
border-bottom: 1px solid white;
}
.item-inner {
display: flex; /* new; nested flex container */
flex: 1; /* new */
/* height: 100%; <-- remove; unnecessary */
/* width: 100%; <-- remove; unnecessary */
/* display: table; <-- remove; unnecessary */
}
a {
display: flex; /* new; nested flex container */
flex: 1; /* new */
align-items: center; /* new; vertically center text */
background: orange;
/* display: table-cell; <-- remove; unnecessary */
/* vertical-align: middle; <-- remove; unnecessary */
}
<div class="container">
<div class="item">
<div class="item-inner">
<a>Button</a>
</div>
</div>
<div class="item">
<div class="item-inner">
<a>Button</a>
</div>
</div>
<div class="item">
<div class="item-inner">
<a>Button</a>
</div>
</div>
</div>