Как выровнять текст по вертикали во flexbox?

425

Я хотел бы использовать flexbox для вертикального выравнивания некоторого контента внутри, <li>но без особого успеха.

Я проверил онлайн, и многие из учебных пособий фактически используют div-обертку, которая получает align-items:centerиз настроек flex на родительском элементе, но мне интересно, возможно ли вырезать этот дополнительный элемент?

В этом случае я решил использовать flexbox, поскольку высота элемента списка будет динамической %.

* {
  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>

стайлер
источник

Ответы:

545

Вместо использования align-self: centerиспользовать align-items: center.

Там нет необходимости менять flex-directionили использовать text-align.

Вот ваш код, с одной настройкой, чтобы все это работало:

ul {
  height: 100%;
}

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

align-selfСвойство применяется к нежестким деталям . За исключением того, что вы liне гибкий элемент, потому что его родитель ul- не имеет display: flexили не display: inline-flexприменяется.

Следовательно, ulконтейнер не является гибким, liне является гибким элементом и не align-selfоказывает никакого влияния.

align-itemsСвойство аналогично align-self, за исключением того, что относится к сгибают контейнеры .

Поскольку liэто гибкий контейнер, align-itemsего можно использовать для вертикального центрирования дочерних элементов.

демонстрационный код


Технически, вот как align-itemsи align-selfработает ...

align-itemsСвойство (на контейнере) устанавливает значение по умолчанию align-self(по пунктам). Следовательно, align-items: centerозначает, что все элементы flex будут установлены в align-self: center.

Но вы можете изменить это значение по умолчанию, настроив align-selfотдельные элементы.

Например, вы можете захотеть столбцы одинаковой высоты, поэтому контейнер установлен в align-items: stretch. Тем не менее, один элемент должен быть закреплен сверху, поэтому он установлен на align-self: flex-start.

пример


Как текст является гибким элементом?

Некоторые люди могут задаваться вопросом, как бег текста ...

<li>This is the text</li>

является дочерним элементом li.

Причина в том, что текст, который явно не заключен в элемент встроенного уровня, алгоритмически оборачивается встроенным блоком. Это делает его анонимным встроенным элементом и потомком родителя.

Из спецификации CSS:

9.2.2.1 Анонимные встроенные блоки

Любой текст, который непосредственно содержится внутри элемента контейнера блока, должен рассматриваться как анонимный встроенный элемент.

Спецификация flexbox предусматривает аналогичное поведение.

4. Гибкие элементы

Каждый дочерний поток в гибком контейнере становится гибким элементом, и каждый непрерывный фрагмент текста, который непосредственно содержится внутри гибкого контейнера, оборачивается в анонимный гибкий элемент.

Следовательно, текст в liявляется гибким элементом.

Майкл Бенджамин
источник
2
Мне нравится align-items: baseline.
Подходит
1
Спасибо за разъяснение и ссылку на концепцию анонимных встроенных блоков ... действительно помогает прояснить, почему некоторые эффекты, которых вы можете достичь методом проб и ошибок, работают так, как они.
Squarecandy
39

Наиболее голосуемым ответом является решение этой конкретной проблемы, опубликованной OP, где содержимое (текст) было заключено в inline-blockэлемент. В некоторых случаях речь может идти о центрировании нормального элемента вертикально внутри контейнера , что также применимо в моем случае, поэтому для этого все, что вам нужно:

align-self: center;
Мохд Абдул Муджиб
источник
25

Лучший шаг - просто вставить flexbox внутрь flexbox . Все, что вам нужно сделать, это дать ребенку align-items: center. Это будет вертикально выравнивать текст внутри его родителя.

// 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
источник
Если вы хотите идеально центрированный текст. text-align:centerне работает в одиночку. Используйте align-items: centerс этим.
Цвенни
8

РЕЗУЛЬТАТ

введите описание изображения здесь

HTML

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

Используйте align-itemsвместо align-selfи я также добавил 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
источник
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>

Анатолий Горчук
источник
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
источник
Ответы только на код не очень полезны ... добавить комментарии или объяснение того, что вы сделали, и почему это работает.
random_user_name
0

С display: flexего помощью вы можете контролировать вертикальное выравнивание 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>

Анкур Праджапати
источник
-6

Вы можете изменить ulи liотображает на tableи table-cell. Тогда, vertical-alignбудет работать для вас:

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
источник
Работает хорошо, пока вы не добавите еще один элемент списка.
Джордж
1
Правда ... Но это никогда не упоминалось
LcSalazar
Вы изменили высоту, чтобы быть на ul вместо li? высота каждого ли будет динамичной, так что я не боюсь использовать это
стайлер
@LcSalazar Обычно вы бы не использовали список, если бы у вас был только один элемент. Для этого и нужны divs.
Бен Виснесс
2
Верно снова ... Но я не говорю, что это идеальный сценарий. Я только что опубликовал решение, которое отвечает на вопрос как есть. Я надеюсь, что эта информация может пригодиться кому-то еще, кто читает ее и имеет другой сценарий ...
LcSalazar