vertical-align não centraliza div: onde ele funciona e o que usar no lugar
vertical-align só age em elementos inline e células de tabela. Veja o que ele faz de verdade, como usar para alinhar ícone e texto, consertar o vão embaixo da imagem e centralizar bloco com flex ou grid.
Quinta, 16h. O card de "Pagamento pendente" precisa do texto no meio da caixa de 120 pixels. Você escreve vertical-align: middle na div, recarrega, e o texto continua grudado no topo. Põe !important, testa vertical-align: center, e nada. A tarde vai embora brigando com uma propriedade que nunca foi feita para isso.
A resposta curta: vertical-align só funciona em elementos inline, inline-block e células de tabela. Numa div comum, que é display: block, ele é ignorado. Para centralizar um bloco dentro de outro, use display: flex com align-items: center ou display: grid com place-items: center no pai. Guarde vertical-align para o que ele faz bem: alinhar ícone com texto na mesma linha e alinhar conteúdo em célula de tabela.
O que vertical-align faz de verdade
O nome engana. A propriedade não alinha um elemento dentro do pai. Ela alinha um elemento inline em relação à linha de texto em que ele está. Pense numa linha de caderno: as letras se apoiam numa linha de base, algumas descem abaixo dela (g, p, q), outras sobem (as maiúsculas, o l, o h). Um ícone, uma imagem ou um span no meio dessa linha precisa de uma regra para saber onde se apoiar. Essa regra é o vertical-align.
Os valores mais usados:
baseline(padrão): a base do elemento fica na linha de base do texto. Para imagem, a base é a borda de baixo.middle: o meio do elemento fica na linha de base do pai mais metade da altura da letra x minúscula. É "meio da letra minúscula", não "meio da caixa".topebottom: alinham com o topo ou o fundo da linha inteira.text-topetext-bottom: alinham com o topo ou o fundo da fonte do pai.sub,supere comprimentos como-0.125em: sobem ou descem o elemento em relação à base.
Em célula de tabela, o significado muda: ali top, middle e bottom posicionam o conteúdo dentro da célula. É por isso que tutoriais antigos, como o que originou este post, ensinavam a transformar a div em display: table-cell para centralizar. Funcionava, mas era um desvio para contornar a falta de ferramenta melhor. Hoje a ferramenta existe.
Em elemento de bloco e em item de flex ou grid, a propriedade não se aplica. O navegador aceita a declaração, não reclama, e não faz nada. As ferramentas de desenvolvedor do Firefox e as versões recentes do Chrome costumam marcar a declaração como sem efeito, com uma dica do motivo.
Como centralizar o card do jeito certo
O card de "Pagamento pendente" tem altura fixa de 120 pixels e um parágrafo dentro. A correção vai no pai, não no texto:
- Abra o inspetor, selecione o elemento que você quer mover e veja o
displaycalculado. - Identifique o pai, que é quem tem a área onde o filho deve ficar centralizado.
- No pai, aplique flex ou grid com alinhamento no eixo vertical.
- Remova o
vertical-align, oline-heightgigante e omargin-topcalculado na mão que sobraram das tentativas.
<div class="card-aviso">
<p>Pagamento pendente</p>
</div>
/* centraliza na vertical */
.card-aviso {
display: flex;
align-items: center;
min-height: 120px;
padding: 0 16px;
}
/* centraliza nos dois eixos */
.card-aviso--meio {
display: grid;
place-items: center;
min-height: 120px;
}
Use min-height em vez de height: se o texto quebrar em três linhas no celular, o card cresce em vez de vazar. Nos navegadores atuais, desde 2024, também existe align-content: center em blocos comuns, sem mudar o display. Se o seu público usa navegador antigo, flex e grid são a aposta segura. Para os detalhes de centralizar nos dois eixos sem número mágico, inclusive com texto de tamanho variável, veja o guia de centralizar um bloco na horizontal e na vertical.
Onde vertical-align é a ferramenta certa
Ícone ao lado do texto
Agora o card ganha um ícone de alerta antes da frase. Os dois são inline, estão na mesma linha, e o ícone aparece um pouco acima ou abaixo do texto. Aqui sim:
<p class="aviso">
<img src="/icones/alerta.svg" width="20" height="20" alt="">
Pagamento pendente
</p>
.aviso img {
vertical-align: middle;
}
/* alternativa: descer o ícone um pouco abaixo da base */
.aviso img.ajuste-fino {
vertical-align: -0.125em;
}
O middle resolve na maioria das fontes. Quando o ícone tem o mesmo tamanho da fonte, um deslocamento pequeno em em costuma ficar mais preciso, porque acompanha o tamanho do texto. Se o card já é flex, outra saída é deixar o align-items: center do pai alinhar ícone e texto como dois itens. O alt="" vazio diz ao leitor de tela que o ícone é decorativo, porque a frase ao lado já informa tudo.
O vão misterioso embaixo da imagem
A foto do produto fica dentro de uma div com borda, e aparecem uns 4 pixels de espaço entre a imagem e a borda de baixo. Ninguém pôs margem. A causa é o baseline: a imagem é inline, apoia a borda de baixo na linha de base do texto, e o espaço abaixo da base fica reservado para as letras que descem. Duas correções, ambas de uma linha:
.foto-produto img { display: block; }
/* ou */
.foto-produto img { vertical-align: top; }
Célula de tabela de verdade
Numa tabela de dados com linhas de alturas diferentes, td { vertical-align: top; } faz o texto curto começar alinhado com o início do texto longo da célula vizinha, o que facilita a leitura. Esse é o uso original da propriedade, e continua correto.
Erros comuns
- Aplicar
vertical-alignnuma div de bloco. A declaração é ignorada sem erro, e você perde tempo achando que o problema é especificidade. - Usar
vertical-align: center. Esse valor não existe; o navegador descarta a declaração inteira. - Colocar a propriedade no filho de um flex. Item de flex não obedece
vertical-align; quem alinha é oalign-itemsdo pai ou oalign-selfdo item. - Centralizar com
line-heightigual à altura da caixa. Funciona com uma linha só e quebra no primeiro texto que pula para a segunda. - Transformar tudo em
display: table-cell. Resolve o centro e cria efeitos colaterais de largura e de margem que ninguém entende depois. - Calcular
margin-topna mão. O número mágico só vale para aquela fonte, aquele texto e aquela tela.
Checklist
- Você conferiu no inspetor o
displaydo elemento antes de mexer no alinhamento. - Centralização de bloco é feita no pai, com flex ou grid.
- A caixa usa
min-height, nãoheightfixa, quando o texto pode crescer. vertical-alignaparece só em elementos inline, inline-block ou células de tabela.- Ícones ao lado de texto estão alinhados com
middleou um deslocamento emem. - Imagens dentro de caixas com borda não deixam vão embaixo.
- Restos de tentativas antigas (
!important, margens calculadas) foram removidos.
Se o botão do card também tem ícone, vale ler sobre ícone com nome no botão para não perder a acessibilidade junto com o alinhamento. E antes de escrever a próxima regra de alinhamento, abra o inspetor e responda: o elemento que você quer centralizar é inline, bloco comum ou item de flex?
Referência: http://www.maujor.com/blog/2006/07/17/propriedade-vertical-align/