J'ai une boîte de flexion horizontale (c'est-à-dire flex-direction: row
, c'est-à-dire côte à côte) avec quelques éléments. Chaque élément peut être constitué d'une seule ligne de texte ou de plusieurs lignes. Je souhaite aligner verticalement le contenu de chaque élément flexible.
Si chaque élément avait un fond transparent, je pourrais facilement utiliser align-items: center
. Cependant, je souhaite que chaque élément soit étiré verticalement, car je souhaite définir un arrière-plan (ou peut-être des bordures, ou peut-être une région cliquable) sur toute la hauteur disponible.
Jusqu'à présent, je sais:
align-items: stretch
align-items: center
Démo disponible à http://codepen.io/denilsonsa/pen/bVBQQNa
ul {
display: flex;
flex-direction: row;
}
ul.first {
align-items: stretch;
}
ul.second {
align-items: center;
}
ul > li {
flex-grow: 1;
flex-shrink: 0;
flex-basis: 5em;
text-align: center;
}
ul > li:nth-child(2) {
background: #CFC;
}
/* Visual styles, just ignore. */
html, body { font-family: sans-serif; font-size: 25px; }
ul, li { list-style: none; margin: 0; padding: 0; }
ul { background: #CCF; width: 25em; }
<ul class="first">
<li>Sample</li>
<li><span>span</span></li>
<li><span>multiple</span> <span>span</span></li>
<li>text <span>span</span></li>
<li>multi<br>line</li>
</ul>
<hr>
<ul class="second">
<li>Sample</li>
<li><span>span</span></li>
<li><span>multiple</span> <span>span</span></li>
<li>text <span>span</span></li>
<li>multi<br>line</li>
</ul>
Questions similaires:
Malheureusement, il est impossible d'obtenir l'effet souhaité en utilisant le balisage exact affiché dans la question.
La solution implique:
display: flex;
sur <li>
.<li>
dans un autre élément .<li>
est maintenant un conteneur flex, nous avons donc besoin d'un autre élément pour empêcher le contenu réel de devenir des éléments flex.<div>
, mais il aurait pu s'agir d'un autre élément.<li>
est un conteneur flex et qu'il ne contient qu'un seul enfant, nous pouvons utiliser align-items
et/ou justify-content
pour aligner ce nouvel et unique enfant.L'arbre DOM ressemble à ceci:
<ul> flex-parent, direction=row
├ <li> flex-item && flex-parent && background && JavaScript clickable area
│ └ <div> flex-item as a single transparent element
│ ├ Actual contents
│ └ Actual contents
├ …
Note: La solution dans cette réponse utilise 2 boîtes flexibles imbriquées. La solution de Michael_B utilise 3 boîtes flexibles imbriquées, car elle présente le défi supplémentaire d’élargir l’élément <a>
pour remplir le <li>
complet. Lequel est préféré dépend de chaque cas. Si je pouvais, j'accepterais les deux réponses.
/* New code: this is the solution. */
ul > li {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
/* Old code below. */
ul {
display: flex;
flex-direction: row;
align-items: stretch;
}
ul > li {
flex-grow: 1;
flex-shrink: 0;
flex-basis: 5em;
text-align: center;
}
ul > li:nth-child(2) {
background: #CFC;
}
/* Visual styles, just ignore. */
html, body { font-family: sans-serif; font-size: 25px; }
ul, li { list-style: none; margin: 0; padding: 0; }
ul { background: #CCF; width: 25em; }
button:focus + ul {
font-size: 14px;
width: auto;
}
<button>Click here to set <code>width: auto</code> and reduce the font size.</button>
<!-- New code: there is a single <div> between each <li> and their contents. -->
<ul>
<li><div>Sample</div></li>
<li><div><span>span</span></div></li>
<li><div><span>multiple</span> <span>span</span></div></li>
<li><div>text <span>span</span></div></li>
<li><div>multi<br>line</div></li>
</ul>
Créez les li
flex-conteneurs avec flex-direction:column
. Je pense que c'est ce que vous recherchez.
html,
body {
font-family: sans-serif;
font-size: 25px;
}
ul,
li {
list-style: none;
margin: 0;
padding: 0;
}
ul {
background: #CCF;
width: 25em;
display: flex;
flex-direction: row;
}
ul.first {
align-items: stretch;
}
ul > li {
flex-grow: 1;
flex-shrink: 0;
flex-basis: 5em;
text-align: center;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
/*outline: 1px dotted #444;*/
}
ul > li:nth-child(2) {
background: #CFC;
}
<ul class="first">
<li>Sample</li>
<li><span>span</span>
</li>
<li><span>multiple</span> <span>span</span>
</li>
<li>text <span>span</span>
</li>
<li>multi
<br>line</li>
</ul>
Je veux que chaque élément soit étiré verticalement, parce que je veux définir un arrière-plan (ou peut-être des frontières, ou peut-être que c'est une région cliquable) à toute la hauteur disponible.
Vous pouvez réaliser cette mise en page sans aucune modification de votre structure HTML. Il n'y a pas besoin de conteneurs supplémentaires.
Vous avez déjà un conteneur Flex principal et un groupe d’éléments Flex. Il suffit de transformer ces éléments flexibles en conteneurs flexibles imbriqués. Cela vous permettra d’aligner le contenu avec les propriétés flex.
(Puisque vous avez mentionné que vous pourriez avoir besoin de régions cliquables, je suis passé de li
à a
elements.)
nav {
display: flex;
background: #CCF;
width: 25em;
}
nav > a {
flex: auto; /* flex-grow: 1, flex-shrink: 1, flex-basis: auto */
text-align: center;
text-decoration: none;
display: flex;
align-items: center;
justify-content: center;
}
nav > a:nth-child(2) {
background: #CFC;
}
html, body {
font-family: sans-serif;
font-size: 25px;
}
<nav>
<a href="">Sample</a>
<a href=""><span>span</span></a>
<a href=""><span>multiple</span> <span>span</span></a>
<a href="">text <span>span</span></a>
<a href="">multi<br>line</a>
</nav>
Notez que le contenu placé directement dans un conteneur flex est enveloppé dans un élément flex anonyme:
De la spec:
Chaque enfant entrant d'un conteneur flex devient un élément flex, et chaque série de texte contigu qui est directement contenue dans un fichier flex Le conteneur est emballé dans un article Flex anonyme.
Ainsi, comme le texte est automatiquement enveloppé dans des éléments flexibles, vous pouvez conserver la hauteur totale de chaque élément (align-items: stretch
du conteneur principal) et centrer verticalement le contenu (align-items: center
des conteneurs imbriqués).
Les éléments flex-child peuvent également être des éléments flex-parent.
*,
*:before,
*:after {
box-sizing: inherit;
}
html {
box-sizing: border-box;
font-family: sans-serif;
font-size: 25px;
}
body {
display: flex;
flex-flow: column nowrap;
background-color: #333;
overflow: hidden;
}
html,
body {
width: 100%;
height: 100%;
padding: 0;
margin: 0;
}
.List {
padding: 0;
margin: 0;
background: #CCF;
width: 25em;
list-style: none;
display: flex;
flex-flow: row nowrap;
justify-content: center;
}
.ListItem {
flex-basis: 5em;
display: flex;
flex-flow: row wrap;
text-align: center;
align-items: center;
}
.ListItem:nth-child(2) {
background: #CFC;
}
.ListItem__content {
width: 100%;
}
<ul class="List">
<li class="ListItem">
<span class="ListItem__content">Sample</span>
</li>
<li class="ListItem">
<span class="ListItem__content">span</span>
</li>
<li class="ListItem">
<span class="ListItem__content">multiple <br> span</span>
</li>
<li class="ListItem">
<span class="ListItem__content">span</span>
</li>
<li class="ListItem">
<span class="ListItem__content">multi<br>line</span></li>
</ul>