Usando margem: automático para alinhar verticalmente um div

113

Portanto, sei que podemos centralizar uma div horizontalmente se usarmos margin:0 auto;. Deve margin:auto auto;funcionar como eu acho que deve funcionar? Centralizá-lo verticalmente também?

Por que também não vertical-align:middle;funciona?

.black {
    position:absolute;
    top:0;
    bottom:0;
    left:0;
    right:0;
    background:rgba(0,0,0,.5);
}
.message {
    background:yellow;
    width:200px;
    margin:auto auto;
    padding:10px;
}
<div class="black">
    <div class="message">
        This is a popup message.
    </div>
</div>

JSFiddle

salvador
fonte
1
Sugiro que leia e implemente a resposta de @zpr abaixo em relação ao Flexbox. É muito bem suportado a partir de hoje e seu css estará muito, muito mais limpo.
Govind Rai
if ((new Date ()). getFullYear ()> 2017) useFlexBox = true;
Brandito,

Respostas:

173

Atualização de agosto de 2020

Embora ainda valha a pena ler o seguinte para obter informações úteis, já temos o Flexbox há algum tempo, então apenas use-o de acordo com esta resposta .


Você não pode usar:

vertical-align:middleporque é não aplicável a elementos nível de bloco

margin-top:autoe margin-bottom:autoporque seus valores usados ​​seriam computados como zero

margin-top:-50%porque os valores de margem baseados em porcentagem são calculados em relação à largura do bloco que contém

Na verdade, a natureza do fluxo de documentos e os algoritmos de cálculo da altura do elemento tornam impossível usar as margens para centralizar um elemento verticalmente dentro de seu pai. Sempre que o valor de uma margem vertical é alterado, ele irá disparar um recálculo da altura do elemento pai (refluxo), que por sua vez irá disparar um recentramento do elemento original ... tornando-o um loop infinito.

Você pode usar:

Algumas soluções alternativas como esta que funcionam para o seu cenário; os três elementos devem ser aninhados da seguinte forma:

.container {
    display: table;
    height: 100%;
    position: absolute;
    overflow: hidden;
    width: 100%;
}
.helper {
    #position: absolute;
    #top: 50%;
    display: table-cell;
    vertical-align: middle;
}
.content {
    #position: relative;
    #top: -50%;
    margin: 0 auto;
    width: 200px;
    border: 1px solid orange;
}
<div class="container">
    <div class="helper">
        <div class="content">
            <p>stuff</p>
        </div>
    </div>
</div

JSFiddle funciona bem de acordo com Browsershot.

ov
fonte
10
#é um hack para ter a regra prefixada apenas interpretada pelo IE7 e inferior. Você pode preferir incluir essas regras em uma folha de estilo específica do IE usando comentários condicionais etc.
ov
2
+1 para a citação das razões pelas quais este é o caso, o cálculo da porcentagem da margem com base na largura foi muito esclarecedor.
ricosrealm,
2
Duvido da declaração de 'loop infinito'.
Barun
105
a humanidade já foi à lua anos atrás e ainda temos que lidar com essa porcaria. alinhar as coisas verticalmente em um navegador, jesus
user151496
3
Na idade> = IE9, position: absolute; top: 50%; transform: translateY(-50%);também é viável e bastante popular ... (ao contrário de top:50%;margin: - $halfHeightvocê não precisa saber a altura com antecedência ...)
Frank Nocke
112

Desde que esta pergunta foi feita em 2012 e já percorremos um longo caminho com o suporte do navegador para flexboxes, eu senti que essa resposta era obrigatória.

Se a exibição de seu contêiner pai for flex, então sim , margin: auto auto(também conhecido como margin: auto) funcionará para centralizá-lo horizontalmente e verticalmente, independentemente de ser um elemento inlineou block.

#parent {
    width: 50vw;
    height: 50vh;
    background-color: gray;
    display: flex;
}
#child {
    margin: auto auto;
}
<div id="parent">
    <div id="child">hello world</div>
</div>

Observe que a largura / altura não precisa ser especificada de forma absoluta, como neste exemplo jfiddle, que usa o tamanho em relação à janela de visualização.

Embora o suporte do navegador para flexboxes esteja em alta no momento da publicação, muitos navegadores ainda não o suportam ou exigem prefixos do fornecedor. Consulte http://caniuse.com/flexbox para obter informações atualizadas de suporte ao navegador.

Atualizar

Como essa resposta recebeu um pouco de atenção, também gostaria de salientar que você não precisa especificar marginse está usando display: flexe gostaria de centralizar todos os elementos no contêiner:

#parent {
    width: 50vw;
    height: 50vh;
    background-color: gray;
    display: flex;
    align-items: center; /* horizontal */
    justify-content: center; /* vertical */
}
<div id="parent">
    <div>hello world</div>
</div>

zpr
fonte
4
pai {display: flex; } criança {margem: auto 0; } é simplesmente ótimo.
Arek Kostrzeba 01 de
Cara, você é um cara do rock, droga, eu não consigo votar em você mais de uma vez !!!
PirateApp
É uma boa resposta quando você também pode ser confundido com o problema do conteúdo adequado. Ao definir flex no contêiner, o div de conteúdo não precisa de nenhuma propriedade para definir.
Eric
1
Esta é de longe a melhor e elegante solução para trabalhar em 2018, obrigado.
SilverSurfer
Gostaria de acrescentar que, a partir de maio de 2018, com esta solução, o texto não alinha verticalmente no meio no IE 11.
Yefu
62

Aqui está a melhor solução que encontrei: http://jsfiddle.net/yWnZ2/446/ Funciona no Chrome, Firefox, Safari, IE8-11 e Edge.

Se você tem uma declarada height( height: 1em, height: 50%, etc.) ou é um elemento onde o navegador sabe a altura ( img, svgou canvaspor exemplo), então tudo que você precisa para centralização vertical é esta:

.message {
    position: absolute;
    top: 0; bottom: 0; left: 0; right: 0;
    margin: auto;
}

Você normalmente desejará especificar um widthou max-widthmais, o conteúdo não se estende por toda a extensão da tela / contêiner.

Se você estiver usando isso para um modal que deseja sempre centralizado na janela de visualização sobrepondo outro conteúdo, use position: fixed;para os dois elementos em vez de position: absolute. http://jsfiddle.net/yWnZ2/445/

Aqui está um artigo mais completo: http://codepen.io/shshaw/pen/gEiDt

shshaw
fonte
3
Isso não o centraliza necessariamente em seu elemento pai. Belo hack se você quiser apenas no centro da página.
Joel Mellon
2
Basta adicionar position: relativeao pai e o elemento será centralizado no pai. Eu fiz um artigo muito maior na Smashing Magazine sobre a técnica, se você quiser ler mais: coding.smashingmagazine.com/2013/08/09/…
shshaw
Às vezes, absoluto é baseado em um pai ou dois (vs o corpo) e o parente pode ser um avô ou bisavô (vs o pai). Talvez aqueles que sabem quando ou por que isso ocorre possam controlar melhor essa técnica - eu nunca realmente examinei essas questões, mas sei que mudar de absoluto para relativo não é em si uma solução para fazer este trabalho. Eu li um pouco do seu artigo e parece que absoluto e relativo vão até o primeiro ancestral absoluto ou relativo, correto?
Joel Mellon
Eu sou um pouco lento. Acabei de reler seu comentário acima. Não percebi que você disse para adicioná-lo ao parent- entendi. Muito obrigado!
Joel Mellon
1
@commonpike O único problema com o IE8 / 9 é se você usa display: tablepara conteúdo de altura variável. Caso contrário, este método deve funcionar conforme o esperado. Leia o artigo para obter mais detalhes gerais. Você também deve ser capaz de testar a visualização completa no IE8 / 9 para ver se há algum problema.
shshaw
22

Edit: é 2020, eu usaria flex box em vez disso.

Resposta original:

Html

<body>
  <div class="centered">
  </div>
</body>

CSS

.centered {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}
Gal Margalit
fonte
não funcionaria para o IE 8 e versões anteriores do ie. Uma vez que a propriedade de transformação é suportada (com o prefixo -ms-) da versão 9.0 e superior. (ou seja, 10 não precisa mais do prefixo).
DevWL 01 de
5
É verdade, eu não me importo com o IE8
Gal Margalit
E o escritor marcou html5 para sua pergunta ☺
Gal Margalit
9

Sei que a pergunta é de 2012, mas descobri a maneira mais fácil de todas e queria compartilhar.

HTML:

<div id="parent">
     <div id="child">Content here</div>
</div>

e CSS:

#parent{
     height: 100%;
     display: table;
}    
#child {
     display: table-cell;
     vertical-align: middle; 
}
Paula Fleck
fonte
7

Se você souber a altura do div que deseja centralizar , poderá posicioná-lo absolutamente dentro de seu pai e definir o topvalor como 50%. Isso colocará o topo do div filho 50% abaixo de seu pai, ou seja, muito baixo. Puxe-o de volta definindo seumargin-top para a metade de sua altura. Então agora você tem o ponto médio vertical do div filho sentado no ponto médio vertical do pai - centralizado verticalmente!

Exemplo:

.black {
    position:absolute;
    top:0;
    bottom:0;
    left:0;
    right:0;
    background:rgba(0,0,0,.5);
}
.message {
    background:yellow;
    width:200px;
    margin:auto auto;
    padding:10px;
    position: absolute;
    top: 50%;
    margin-top: -25px;
    height: 50px;
}
<div class="black">
    <div class="message">
        This is a popup message.
    </div>
</div>

http://jsfiddle.net/yWnZ2/2/

tufo
fonte
1
margin-topnão pode ser definido em% em relação à altura do elemento, então você acabará com uma correção dependente das dimensões
ov
1
O que é ... exatamente o que eu disse na minha resposta? "Se você souber a altura da div que deseja centralizar". E eu não disse que o OP deveria usar% em margin-top.
tuff
Não concordo com a solução, pois ela bloqueia você em uma altura de elemento predefinida - mas seu comentário faz sentido. Você pode querer refletir isso na resposta
ov
3
OK, coloquei em negrito a parte que você esqueceu, espero que esteja mais claro agora.
tuff
1
@ov: Se o elemento não tiver uma altura fixa, você pode apenas usar JS para obter a altura calculada e, em seguida, definir a margem superior negativa de acordo. Este ainda é o melhor método para centralizar verticalmente, na minha opinião.
DAGUY
3

Essas duas soluções requerem apenas dois elementos aninhados.
Primeiro - Posicionamento relativo e absoluto se o conteúdo for estático (centralização manual).

.black {
    position:relative;
    min-height:500px;
    background:rgba(0,0,0,.5);

}
.message {
    position:absolute;
    margin: 0 auto;
    width: 180px;
    top: 45%; bottom:45%;  left: 0%; right: 0%;
}

https://jsfiddle.net/GlupiJas/5mv3j171/

ou para design fluido - para centro de conteúdo exato, use o exemplo abaixo:

.message {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

https://jsfiddle.net/GlupiJas/w3jnjuv0/

Você precisa definir 'min-height' caso o conteúdo ultrapasse 50% da altura da janela. Você também pode manipular essa altura com consulta de mídia para dispositivos móveis e tablets. Mas apenas se você jogar com design responsivo.

Acho que você poderia ir mais longe e usar um script JavaScript / JQuery simples para manipular a altura mínima ou a altura fixa se houver necessidade por algum motivo.

Segundo - se o conteúdo for fluido, você também pode usar as propriedades css de tabela e célula de tabela com alinhamento vertical e alinhamento de texto centralizado:

/*in a wrapper*/  
display:table;   

e

/*in the element inside the wrapper*/
display:table-cell;
vertical-align: middle;
text-align: center;

Funciona e escala perfeitamente, muitas vezes usado como solução de web design responsivo com layouts de grade e consulta de mídia que manipulam a largura do objeto.

.black {
    display:table;
    height:500px;
    width:100%;
    background:rgba(0,0,0,.5);

}
.message {
    display:table-cell;
    vertical-align: middle;
    text-align: center;
}

https://jsfiddle.net/GlupiJas/4daf2v36/

Eu prefiro a solução de tabela para a centralização exata do conteúdo, mas em alguns casos o posicionamento absoluto relativo fará um trabalho melhor, especialmente se não quisermos manter a proporção exata do alinhamento do conteúdo.

DevWL
fonte
2

.black {
    display:flex;
    flex-direction: column;
    height: 200px;
    background:grey
}
.message {
    background:yellow;
    width:200px;
    padding:10px;
    margin: auto auto;
}
<div class="black">
    <div class="message">
        This is a popup message.
    </div>
</div>

Seetpal Singh
fonte
Você poderia compartilhar conosco, como é essa solução? Além disso, vejo sua "mensagem pop-up" na parte inferior não centralizada
Alex
Perdi algo, mas agora é refinado para manter o div no meio verticalmente. você pode verificar agora.
Seetpal singh
0

Não existe uma maneira fácil de centralizar o div verticalmente, o que funcionaria em todas as situações.

No entanto, existem muitas maneiras de fazer isso, dependendo da situação.

Aqui estão alguns deles:

  • Defina o preenchimento superior e inferior do elemento pai, por exemplo, preenchimento: 20px 0px 20px 0px
  • Use a tabela, a célula da tabela centraliza seu conteúdo verticalmente
  • Defina a posição relativa do elemento pai e os divs que deseja centralizar verticalmente como absoluto e estilize-o como superior: 50px; inferior: 50px; por exemplo

Você também pode procurar no google por "centralização vertical css"

hasu
fonte
0

altura variável, margem superior e inferior automática

.black {background:rgba(0,0,0,.5);
width: 300px;
height: 100px;
display: -webkit-flex; /* Safari */
display: flex;}
.message{
background:tomato;
margin:auto;
padding:5%;
width:auto;
}
<div class="black">
<div class="message">
    This is a popup message.
</div>

altura variável, margem superior e inferior automática

user3668456
fonte
0

Usando Flexbox:

HTML:

<div class="container">
  <img src="http://lorempixel.com/400/200" />
</div>

CSS:

.container {
  height: 500px;
  display: flex;
  justify-content: center; /* horizontal center */
  align-items: center;     /* vertical center */
}

Ver resultado

DanielBlazquez
fonte
0
.black {
    position:absolute;
    top:0;
    bottom:0;
    left:0;
    right:0;
    background:rgba(0,0,0,.5);
}
.message {
    position: absolute;
    top:50%;
    left: 50%;
    transform: translate(-50%, -50%);
    background:yellow;
    width:200px;
    padding:10px;
}

 - 


----------


<div class="black">
<div class="message">
    This is a popup message.
</div>
Sudipto Chakraborty
fonte