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: stretchvenue du parent. Pour que la stretchvaleur 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 heightproprié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-innerdit à 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: 1rè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-growcomme référence parent adéquate s'il est utilisé en conjonction avecflex-basis (toute valeur numérique fonctionne ( autone 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-heightet max-heightne sont pas acceptables. Ce doit être la heightpropriété.
Plus de détails ici: Utilisation de la heightpropriété CSS et des valeurs de pourcentage
2. Positionnement relatif et absolu CSS
S'applique position: relativeau 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 .itemou .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 buttonun enfant de .containerou .itemet 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: stretchvenue du parent. Pour que la stretchvaleur 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>