Comment aligner verticalement du texte à l'intérieur d'une flexbox?

425

Je voudrais utiliser flexbox pour aligner verticalement du contenu à l'intérieur d'un <li>mais sans grand succès.

J'ai vérifié en ligne et de nombreux didacticiels utilisent en fait un div wrapper qui obtient les align-items:centerparamètres flex sur le parent, mais je me demande s'il est possible de supprimer cet élément supplémentaire?

J'ai choisi d'utiliser flexbox dans ce cas car la hauteur de l'élément de liste sera une dynamique %.

* {
  padding: 0;
  margin: 0;
}

html,
body {
  height: 100%;
}

ul {
  height: 100%;
}

li {
  display: flex;
  justify-content: center;
  align-self: center;
  background: silver;
  width: 100%;
  height: 20%;
}
<ul>
  <li>This is the text</li>
</ul>

styler
la source

Réponses:

545

Au lieu d'utiliser align-self: centeruse align-items: center.

Il n'est pas nécessaire de modifier flex-directionou d'utiliser text-align.

Voici votre code, avec un ajustement, pour que tout fonctionne:

ul {
  height: 100%;
}

li {
  display: flex;
  justify-content: center;
  /* align-self: center;    <---- REMOVE */
  align-items: center;   /* <---- NEW    */
  background: silver;
  width: 100%;
  height: 20%; 
}

La align-selfpropriété s'applique aux éléments flexibles . Sauf que votre lin'est pas un élément flexible parce que son parent - le ul- n'a pas display: flexou n'a pas display: inline-flexappliqué.

Par conséquent, uln'est pas un conteneur flexible, lin'est pas un élément flexible et align-selfn'a aucun effet.

La align-itemspropriété est similaire à align-self, sauf qu'elle s'applique aux conteneurs flexibles .

Étant donné que le liest un conteneur flexible, align-itemspeut être utilisé pour centrer verticalement les éléments enfants.

démo codepen


Techniquement, voici comment align-itemset align-selftravailler ...

La align-itemspropriété (sur le conteneur) définit la valeur par défaut de align-self(sur les éléments). Par conséquent, align-items: centersignifie que tous les éléments flexibles seront définis sur align-self: center.

Mais vous pouvez remplacer cette valeur par défaut en ajustant les align-selféléments individuels.

Par exemple, vous souhaiterez peut-être des colonnes de hauteur égale, de sorte que le conteneur est défini sur align-items: stretch. Cependant, un élément doit être épinglé en haut, il est donc défini sur align-self: flex-start.

exemple


Comment le texte est-il un élément flexible?

Certaines personnes se demandent peut-être comment une série de textes ...

<li>This is the text</li>

est un élément enfant du li.

La raison en est que le texte qui n'est pas explicitement encapsulé par un élément de niveau en ligne est encapsulé de manière algorithmique par une zone en ligne. Cela en fait un élément en ligne anonyme et un enfant du parent.

De la spécification CSS:

9.2.2.1 Boîtes en ligne anonymes

Tout texte contenu directement dans un élément de conteneur de bloc doit être traité comme un élément en ligne anonyme.

La spécification flexbox prévoit un comportement similaire.

4. Articles flexibles

Chaque enfant entrant d'un conteneur flexible devient un élément flexible et chaque série de texte contiguë contenue directement dans un conteneur flexible est enveloppée dans un élément flexible anonyme.

Par conséquent, le texte dans le liest un élément flexible.

Michael Benjamin
la source
2
J'aime align-items: baseline. Bon pour différentes hauteurs provenant de différents caractères Unicode, etc.
qräbnö
1
Merci d'avoir expliqué et lié au concept de boîtes en ligne anonymes ... aide vraiment à clarifier pourquoi certains effets que vous pouvez obtenir par essais et erreurs fonctionnent comme ils le font.
squarecandy
39

La réponse la plus votée est de résoudre ce problème spécifique publié par OP, où le contenu (texte) était enveloppé dans un inline-blockélément. Dans certains cas, il peut s'agir de centrer un élément normal verticalement à l'intérieur d'un conteneur , ce qui s'applique également dans mon cas, donc pour cela, tout ce dont vous avez besoin est:

align-self: center;
Mohd Abdul Mujib
la source
25

La meilleure chose à faire est d' imbriquer simplement une boîte flexible à l'intérieur d'une boîte flexible . Il vous suffit de donner à l'enfant align-items: center. Cela alignera verticalement le texte à l'intérieur de son parent.

// Assuming a horizontally centered row of items for the parent but it doesn't have to be
.parent {
  align-items: center;
  display: flex;
  justify-content: center;
}

.child {
  display: flex;
  align-items: center;
}
serraosays
la source
Si vous voulez un texte centré parfait. text-align:centerne fonctionne pas seul. À utiliser align-items: centeravec.
Tzwenni
8

RÉSULTAT

entrez la description de l'image ici

HTML

<ul class="list">
  <li>This is the text</li>
  <li>This is another text</li>
  <li>This is another another text</li>
</ul>

Utilisez align-itemsau lieu de align-selfet j'ai également ajouté flex-directionà column.

CSS

* {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
}

html,
body {
  height: 100%;
}

.list {
  display: flex;
  justify-content: center;
  flex-direction: column;  /* <--- I added this */
  align-items: center;   /* <--- Change here */
  height: 100px;
  width: 100%;
  background: silver;
}

.list li {  
  background: gold;
  height: 20%; 
}
Wilson
la source
1

* {
  padding: 0;
  margin: 0;
}

html,
body {
  height: 100%;
}

ul {
  height: 100%;
}

li {
 display: flex;
 justify-content: center;
 align-items: center;
 background: silver;
 width: 100%;
 height: 20%;
}
<ul>
  <li>This is the text</li>
</ul>

Anatoly Gorchuk
la source
0

* {
  padding: 0;
  margin: 0;
}
html, body {
  height: 100%;
}
ul {
  height: 100%;
}
li {
  display: flex;
  justify-content: center;
  align-items:center;
  background: silver;
  width: 100%;
  height: 20%;
}
<ul>
  <li>This is the text</li>
</ul>

Swapnil
la source
Les réponses uniquement codées ne sont pas très utiles ... ajoutez des commentaires ou une explication de ce que vous avez fait et pourquoi cela fonctionne.
random_user_name
0

À l'aide de display: flexvous pouvez contrôler l'alignement vertical des éléments HTML.

.box {
  height: 100px;
  display: flex;
  align-items: center; /* Vertical */
  justify-content: center; /* Horizontal */
  border:2px solid black;
}

.box div {
  width: 100px;
  height: 20px;
  border:1px solid;
}
<div class="box">
  <div>Hello</div>
  <p>World</p>
</div>

Ankur prajapati
la source
-6

Vous pouvez changer le ulet liaffiche à tableet table-cell. Alors, vertical-aligntravaillerait pour vous:

ul {
    height: 20%;
    width: 100%;
    display: table;
}

li {
    display: table-cell;
    text-align: center;
    vertical-align: middle;
    background: silver;
    width: 100%; 
}

http://codepen.io/anon/pen/pckvK

LcSalazar
la source
Fonctionne bien jusqu'à ce que vous y ajoutiez un autre élément de liste.
George
1
C'est vrai ... Mais cela n'a jamais été mentionné
LcSalazar
vous avez changé la hauteur pour être sur l'ul au lieu du li? chaque hauteur de li sera dynamique donc ce n'est pas quelque chose que je pourrais utiliser im peur
styler
@LcSalazar En règle générale, vous n'utiliseriez pas de liste si vous n'aviez l'intention d'avoir qu'un seul élément. C'est à ça que servent les divs.
Ben Visness
2
Encore une fois ... Mais je ne dis pas que c'est le scénario parfait. Je viens de publier une solution qui répond à la question telle quelle. J'espère que cette information pourra être utile à quelqu'un d'autre qui la lira et aura un autre scénario ...
LcSalazar