Por que o alinhamento vertical: middle não está funcionando no meu intervalo ou div?

246

Estou tentando centralizar verticalmente um elemento spanou divdentro de outro divelemento. No entanto, quando eu coloco vertical-align: middle, nada acontece. Eu tentei alterar as displaypropriedades de ambos os elementos, e nada parece funcionar.

É o que estou fazendo atualmente na minha página da web:

.main {
  height: 72px;
  vertical-align: middle;
  border: 1px solid black;
  padding: 2px;
}
    
.inner {
  vertical-align: middle;
  border: 1px solid red;    
}
    
.second {
  border: 1px solid blue; 
}
<div class="main">
  <div class="inner">
    This box should be centered in the larger box
    <div class="second">Another box in here</div>
  </div>
</div>

Aqui está um jsfiddle da implementação, mostrando que ela não funciona: http://jsfiddle.net/gZXWC/

Brad
fonte

Respostas:

207

Esta parece ser a melhor maneira - já passou algum tempo desde o meu post original e é isso que deve ser feito agora: http://jsfiddle.net/m3ykdyds/200

/* CSS file */

.main {
    display: table;
}

.inner {
    border: 1px solid #000000;
    display: table-cell;
    vertical-align: middle;
}

/* HTML File */
<div class="main">
    <div class="inner"> This </div>
</div>
Charles Addis
fonte
2
Então, como alguém faz o que o OP quer fazer?
Ryan Mortensen
Alguma idéia sobre parágrafos de linha variável? ie se não há como saber se serão uma ou duas linhas. Eu precisaria usar o jQuery então?
Foochow
E se a altura precisar ser dinâmica, qual é a solução?
Murhaf Sousli
não deve ser a resposta aceita, depende da altura do conhecimento de '.inner'; portanto, não exatamente o que o OP estava pedindo e algumas respostas muito melhores abaixo, consulte as respostas @timbergus ou Tim Perkins ', bem abaixo do fundo.
Mike-source
@ mike-source, sabendo que a altura do inner é 100% possível, mesmo que a altura seja dinâmica, já que um pouco de javascript pode descobrir isso e alterar dinamicamente a regra CSS para esse objeto DOM.
Charles Addis
143

Usando CSS3:

<div class="outer">
   <div class="inner"/>
</div>

Css:

.outer {
  display : flex;
  align-items : center;
  justify-content: center;
}

Nota: Isso pode não funcionar nos IE antigos

user1782556
fonte
16
Isso é suportado por todos os principais navegadores modernos e pela solução mais simples e limpa.
18715 Sam
2
Lembre- inline-flexse também de ter vários elementos seguidos dentro do elemento interno.
Dan Nissenbaum
1
No meu caso, como também queria centralizar o conteúdo do .inner horizontalmente, tive que adicionar .inner { width: 100%; }. Dessa forma, parece funcionar, .outer { display: table; } .inner { display: table-cell; vertical-align: middle; }mas sem forçar uma largura mínima.
Bart S
I utilizado justify-content: center;para alinhar na horizontal, que funcionou muito bem
Ruth Young
140

Tente isso, funciona muito bem para mim:

/* Internet Explorer 10 */
display:-ms-flexbox;
-ms-flex-pack:center;
-ms-flex-align:center;

/* Firefox */
display:-moz-box;
-moz-box-pack:center;
-moz-box-align:center;

/* Safari, Opera, and Chrome */
display:-webkit-box;
-webkit-box-pack:center;
-webkit-box-align:center;

/* W3C */
display:box;
box-pack:center;
box-align:center;
Mahendra Liya
fonte
4
excelente resposta, isso me deu uma solução totalmente funcional que não causou outros problemas comuns (um aplicativo usando jquerymobile + phonegap e todas as outras soluções levaram a problemas de dimensionamento de css e div). Apenas para salientar que esses parâmetros precisam ser adicionados a um bloco CSS específico para os elementos a serem centralizados / mediados, por exemplo: #element span {height:100%;display:-webkit-box;-webkit-box-pack:center;-webkit-box-align:center;}- observe que a altura é importante para garantir que a extensão herda toda a altura do seu contêiner (provavelmente uma div), caso contrário você ainda não terá a centralização vertical!
Andy Lorenz
BTW, você pode escrever código flexbox padrão sem prefixos navegador e, em seguida, se navegador prefixado com autoprefixer github.com/postcss/autoprefixer ou via online demonstração simevidas.jsbin.com/gufoko/quiet
starikovs
2
valor da propriedade inválida boxemdisplay
Joaquinglezsantos 17/02
Além disso, a resposta do @ user1782556 funciona melhor quando a caixa externa possui preenchimento.
iautomation
34

Definir a altura da linha para a mesma altura em que contém div também funcionará

DEMO http://jsfiddle.net/kevinPHPkevin/gZXWC/7/

.inner {
    line-height:72px;
    border: 1px solid #000000;
}
Kevin Lynch
fonte
1
Eu publiquei um link que explicava esse método também. Porém, não é o meu método preferido, se o restante do layout não tiver tamanho fixo - eu deparei com problemas em diferentes viewports de tamanho com esse método.
Charles Addis
2
sim, a técnica de altura da linha funciona bem, mas SOMENTE SE você tiver conteúdo de linha única. Linhas adicionais serão perdidas / serão derramadas fora do contêiner e você precisará começar novamente!
Andy Lorenz
a) line-heighttambém mudará a altura do elemento interno. b) O elemento interno ainda não está centralizado com precisão na vertical. c) Não funciona em elementos que não contêm texto, por exemplo:, <img>ou elementos com altura fixa.
Alph.Dev
Também pode falhar no sistema operacional cruzado (Windows / Mac) devido a diferenças de renderização de fonte
LocalPCGuy 27/10/2015
1
Isso é muito imprevisível e geralmente resulta em altura extra no contêiner.
Undistraction
25

Caso você não possa confiar no flexbox ... Coloque .childno .parentcentro. Funciona quando os tamanhos de pixel são desconhecidos (em outras palavras, sempre) e sem problemas com o IE9 + também.

.parent { position: relative; }

.child {
    position: absolute;
    top : 50%;
    left: 50%;
    -ms-transform: translate(-50%, -50%);
    transform    : translate(-50%, -50%);    
}
<div class="parent" style="background:lightyellow; padding:6em"> 
  <div class="child" style="background:gold; padding:1em">&mdash;</div> 
</div>

kornieff
fonte
Esta é realmente a solução mais bem feito, especialmente desde que a maioria dos projetos que eu vi compatibilidade IE9 até agora precisa
Jabberwocky
20

Você deve colocar vertical-align: middleo elemento interno, não o externo. Defina a line-heightpropriedade no elemento externo para corresponder à heightdo elemento externo. Em seguida, defina display: inline-blocke line-height: normalno elemento interno. Ao fazer isso, o texto no elemento interno será quebrado com uma altura de linha normal. Funciona no Chrome, Firefox, Safari e IE 8+

.main {
    height: 72px;
    line-height:72px;
    border: 1px solid black;
}
.inner {
    display: inline-block;
    vertical-align: middle;
    line-height: normal;
}
<div class="main">
    <div class="inner">Vertically centered text</div>
</div>

Violino

Tim Perkins
fonte
Esta é provavelmente a maneira mais simples ... todas as outras respostas nesta página são desnecessariamente desajeitadas / hacky OU não são suportadas em navegadores antigos OU dependem do conhecimento da altura do elemento interno. Você realmente não precisa do line-height: normal;e display:inline;também funciona. O bônus desse método é que ele não interfere text-align:center;, com o qual o uso display: table-cell;pode criar problemas. Muitas vezes, queremos alinhar horizontalmente e verticalmente. Veja este violino editado: jsfiddle.net/br090prs/36
mike-source
2
@ mike-source a razão para usar line-height: normale display: inline-blocké para que o texto interno seja quebrado corretamente. Se você tiver certeza de que o texto na div interna nunca será quebrado, essas propriedades não serão necessárias.
Tim Perkins
Desde que a Microsoft terminou o suporte para versões antigas do IE , usei o flexbox para esse tipo de coisa (como sugeriu @ user1782556). Minha resposta original é o caminho a seguir, se você ainda precisar oferecer suporte ao IE 10 ou mais antigo.
Tim Perkins
100% concorda, mas eu ainda não optaria pessoalmente pelo flex box, apenas 76% dos navegadores o suportam totalmente a partir de maio de 2016 (94% se você incluir suporte parcial), consulte: caniuse.com/#search=flexible% 20box . Está chegando muito perto de ser a opção mais sensata, dependendo da sua base de usuários.
Mike-source
10

Usei isso para alinhar tudo no centro da div do wrapper, caso isso ajude alguém - achei mais simples:

div.wrapper {
  /* --- This works --- */
  display: flex;
  /* Align Vertically */
  align-items: center;
  /* Align Horizontally */
  justify-content: center;
  /* --- ---------- ----- */
  width: 100%;
  height:100px;
  background-color: blue;
}
div.inner {
  width: 50px;
  height: 50px;
  background-color: orange;
}
<div class="wrapper">
  <div class="inner">
  </div>
</div>

Ruth Young
fonte
7

Aqui você tem um exemplo de duas maneiras de fazer um alinhamento vertical. Eu os uso e eles funcionam muito bem. Um é usando posicionamento absoluto e o outro usando flexbox .

Exemplo de alinhamento vertical

Usando o flexbox, você pode alinhar um elemento sozinho dentro de outro elemento com o display: flex;uso align-self. Se você precisar alinhá-lo horizontalmente, poderá usar align-itemse justify-contentno contêiner.

Se você não quiser usar o flexbox, poderá usar a propriedade position. Se você tornar o contêiner relativo e o conteúdo absoluto, o conteúdo poderá se mover livremente dentro do contêiner. Portanto, se você usar top: 0;e left: 0;no conteúdo, ele será posicionado no canto superior esquerdo do contêiner.

Posicionamento absoluto

Para alinhá-lo, basta alterar as referências superior e esquerda para 50%. Isso posicionará o conteúdo no centro do contêiner no canto superior esquerdo do conteúdo.

Alinhar no meio do contêiner

Portanto, você precisa corrigir isso traduzindo o conteúdo com metade do tamanho para a esquerda e a parte superior.

Absoluto centrado

Timbergus
fonte
5

Aqui está um ótimo artigo sobre como alinhar veticamente. Gosto da maneira flutuante.

http://www.vanseodesign.com/css/vertical-centering/

O HTML:

<div id="main">
    <div id="floater"></div>
    <div id="inner">Content here</div>
</div>

E o estilo correspondente:

#main {
   height: 250px;
}

#floater {
   float: left;
   height: 50%;
   width: 100%;
   margin-bottom: -50px;
}

#inner {
   clear: both;
   height: 100px;
}
Dory Zidon
fonte
3
Acho que se você definir a altura do bloco interno, invalida o conceito de centralização vertical adequada. O OPS estava pedindo para torná-lo automático, então eu imagino que isso significa que a altura da caixa interna não é conhecida no momento da concepção.
Alexis Wilke
5

HTML

<div id="myparent">
  <div id="mychild">Test Content here</div>
</div>

CSS

#myparent {
  display: table;
}
#mychild {
  display: table-cell;
  vertical-align: middle;
}

Definimos a div pai para exibir como uma tabela e a div filho para exibir como uma célula da tabela. Podemos então usar o alinhamento vertical na div filho e definir seu valor para o meio. Qualquer coisa dentro dessa div criança será centralizada verticalmente.

Brijesh Patel
fonte
4

É simples. Basta adicionar display:table-cellna sua classe principal.

.main {
  height: 72px;
  vertical-align: middle;
  display:table-cell;
  border: 1px solid #000000;
}

Confira este jsfiddle !

RizonBarns
fonte
4

Aqui está a solução mais simples e mais recente - não há necessidade de alterar nada, basta adicionar três linhas de regras CSS ao seu contêiner da div em que você deseja se concentrar. Eu amo Flex Box#LoveFlexBox

.main {
  /* I changed height to 200px to make it easy to see the alignment. */
  height: 200px;
  vertical-align: middle;
  border: 1px solid #000000;
  padding: 2px;
  
  /* Just add the following three rules to the container of which you want to center at. */
  display: flex;
  flex-direction: column;
  justify-content: center;
  /* This is true vertical center, no math needed. */
}
.inner {
  border: 1px solid #000000;
}
.second {
  border: 1px solid #000000;
}
<div class="main">
  <div class="inner">This box should be centered in the larger box
    <div class="second">Another box in here</div>
  </div>
  <div class="inner">This box should be centered in the larger box
    <div class="second">Another box in here</div>
  </div>
</div>

Bônus

o justify-contentvalor pode ser definido para as seguintes opções:

  • flex-start, que alinhará a div filho até onde o fluxo flexível começa em seu contêiner pai. Nesse caso, ele permanecerá no topo.

  • center, que alinhará a div filho ao centro do contêiner pai. Isso é realmente legal, porque você não precisa adicionar uma div adicional para envolver todos os filhos para colocar o wrapper em um contêiner pai para centralizar os filhos. Por esse motivo, esse é o verdadeiro centro vertical (no column flex-directionarquivo. Da mesma forma, se você alterar o flow-directionpara row, ele ficará centralizado horizontalmente.

  • flex-end, que alinhará a div filho até onde o fluxo flexível termina em seu contêiner pai. Nesse caso, ele será movido para o fundo.

  • space-between, que espalhará todos os filhos desde o início do fluxo até o final do fluxo. Se a demonstração, eu adicionei outra div filho, para mostrar que eles estão espalhados.

  • space-around, semelhante a space-between, mas com metade do espaço no início e no final do fluxo.

Downhillski
fonte
Solução perfeita. Os navegadores incompatíveis podem deixar o conteúdo desalinhado e o usuário deve lidar com ele ou atualizar seu navegador.
twicejr
0

Como vertical-alignfunciona como esperado em um td, você pode colocar uma única célula tableno divpara alinhar seu conteúdo.

<div>
    <table style="width: 100%; height: 100%;"><tr><td style="vertical-align: middle; text-align: center">
        Aligned content here...
    </td></tr></table>
</div>

Desajeitado, mas funciona até onde eu sei. Pode não ter os inconvenientes das outras soluções alternativas.

Smig
fonte
5
Não, por favor, não há mais mesas. CSS pode fazer isso de uma maneira limpa. Não há necessidade de usar <table> neste caso.
enguerranws
0

Basta colocar o conteúdo dentro de uma tabela com altura 100% e definir a altura para a div principal

<div style="height:80px;border: 1px solid #000000;">
<table style="height:100%">
<tr><td style="vertical-align: middle;">
  This paragraph should be centered in the larger box
</td></tr>
</table>
</div>
Ramiro Mosquera
fonte
0

Para centralizar verticalmente um elemento de amplitude ou div dentro de outra div, adicione a posição relativa à div pai e a posição absoluta à div filho. Agora, a div filho pode ser posicionada em qualquer lugar dentro da div. Exemplo abaixo centraliza horizontal e verticalmente.

<div class="parent">
    <div class="child">Vertically and horizontally centered child div</div>
</div>

css:

.parent{
    position: relative;
}
.child{
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    margin: auto;
}
Toki
fonte
0

Essa é uma abordagem moderna e utiliza a funcionalidade CSS Flexbox. Agora você pode alinhar verticalmente o conteúdo no contêiner pai, adicionando esses estilos ao .maincontêiner

.main {
        display: flex;
        flex-direction: column;
        justify-content: center;
}

E você está pronto para ir!

Kingsley Gyimah
fonte