Como alinhar verticalmente o texto dentro de uma caixa flexível?

424

Gostaria de usar o flexbox para alinhar verticalmente algum conteúdo dentro de um, <li>mas sem grande sucesso.

Eu verifiquei online e muitos dos tutoriais realmente usam uma div de wrapper que obtém as align-items:centerconfigurações flex no pai, mas estou pensando se é possível cortar esse elemento adicional?

Optei por usar o flexbox nesse caso, pois a altura do item da lista será dinâmica %.

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

estilista
fonte

Respostas:

544

Em vez de usar align-self: centeruse align-items: center.

Não há necessidade de alterar flex-directionou usar text-align.

Aqui está o seu código, com um ajuste, para fazer tudo funcionar:

ul {
  height: 100%;
}

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

A align-selfpropriedade se aplica aos itens flexíveis . Exceto que o liitem não é um item flexível porque o pai - o ul- não possui display: flexou se display: inline-flexaplica.

Portanto, ulnão é um contêiner flexível, linão é um item flexível e align-selfnão tem efeito.

A align-itemspropriedade é semelhante a align-self, exceto se aplica a contêineres flexíveis .

Como o licontainer é flexível, align-itemspode ser usado para centralizar verticalmente os elementos filhos.

demo codepen


Tecnicamente, aqui está como align-itemse como align-selffunciona ...

A align-itemspropriedade (no contêiner) define o valor padrão de align-self(nos itens). Portanto, align-items: centersignifica que todos os itens flexíveis serão definidos como align-self: center.

Mas você pode substituir esse padrão ajustando os align-selfitens individuais.

Por exemplo, você pode querer colunas de altura igual, para que o contêiner esteja definido como align-items: stretch. No entanto, um item deve ser fixado na parte superior, para que esteja definido como align-self: flex-start.

exemplo


Como o texto é um item flexível?

Algumas pessoas podem estar se perguntando como uma sequência de texto ...

<li>This is the text</li>

é um elemento filho do li.

O motivo é que o texto que não é explicitamente quebrado por um elemento de nível embutido é quebrado por algoritmos por uma caixa embutida. Isso o torna um elemento inline anônimo e filho do pai.

A partir da especificação CSS:

9.2.2.1 Caixas em linha anônimas

Qualquer texto que esteja diretamente contido em um elemento de contêiner de bloco deve ser tratado como um elemento inline anônimo.

A especificação flexbox fornece um comportamento semelhante.

4. Itens Flex

Cada filho em fluxo de um contêiner flexível se torna um item flexível e cada execução contígua de texto que está diretamente contida dentro de um contêiner flexível é agrupada em um item flexível anônimo.

Portanto, o texto no lié um item flexível.

Michael Benjamin
fonte
2
Eu gosto align-items: baseline. Bom para diferentes alturas provenientes de diferentes caracteres unicode etc.
qräbnö
1
Obrigado por explicar e vincular ao conceito de caixas em linha anônimas ... realmente ajuda a esclarecer por que alguns efeitos que você pode obter por tentativa e erro funcionam da maneira que funcionam.
squarecandy 23/09/19
39

A resposta mais votada é para resolver esse problema específico publicado pelo OP, onde o conteúdo (texto) estava sendo quebrado dentro de um inline-blockelemento. Alguns casos podem ser sobre a centralização vertical de um elemento normal dentro de um contêiner , o que também se aplica ao meu caso, portanto, tudo o que você precisa é:

align-self: center;
Mohd Abdul Mujib
fonte
25

A melhor jogada é apenas aninhar uma caixa flexível dentro de uma caixa flexível . Tudo que você tem a fazer é dar à criança align-items: center. Isso alinhará verticalmente o texto dentro de seu pai.

// 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
fonte
Se você deseja um texto centralizado perfeito. text-align:centernão funciona sozinho. Use align-items: centercom ele.
Tzwenni 26/02
8

RESULTADO

insira a descrição da imagem aqui

HTML

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

Use em align-itemsvez de align-selfe eu também adicionei flex-directiona 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
fonte
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
fonte
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
fonte
As respostas somente de código não são muito úteis ... adicione comentários ou uma explicação do que você fez e por que funciona.
Random_user_name 01/03/19
0

Usando display: flexvocê pode controlar o alinhamento vertical dos elementos 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
fonte
-6

Você pode alterar o ule liexibe para tablee table-cell. Então, vertical-alignfuncionaria para você:

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
fonte
Funciona bem até você adicionar outro item da lista.
George George
1
Verdade ... Mas isso nunca foi mencionado
LcSalazar
você mudou a altura para ficar na ul em vez da li? cada altura li será dinâmico, de modo que isso não é algo que eu poderia usar im medo
styler
@LcSalazar Você normalmente não usaria uma lista se pretendesse ter apenas um item. É para isso que servem os divs.
Ben Visness
2
É verdade novamente ... Mas não estou dizendo que este é o cenário perfeito. Acabei de publicar uma solução que responde à pergunta como ela é. Espero que esta informação pode vir a calhar para outra pessoa que lê-lo e tem um outro cenário ...
LcSalazar