Como centralizar a div verticalmente dentro da div principal absolutamente posicionada


146

Estou tentando obter um contêiner azul no meio do rosa, mas parece vertical-align: middle;que não funciona nesse caso.

<div style="display: block; position: absolute; left: 50px; top: 50px;">
    <div style="text-align: left; position: absolute;height: 56px;vertical-align: middle;background-color: pink;">
        <div style="background-color: lightblue;">test</div>
    </div>
</div>

Resultado:

insira a descrição da imagem aqui

Expectativa:

insira a descrição da imagem aqui

Por favor, sugira como posso conseguir isso.

Jsfiddle


1
Existe uma razão para você estar usando em position: absolutequalquer lugar?
Vucko

os vertical-align: middle;trabalhos com display: inline-blockou layout da tabela
ctf0


@ Vucko yes - isso é um pré-requisito, pois esta é apenas uma versão simplificada de um layout muito complexo, mas a posição absoluta nas duas divs superiores é fundamental.
Vladimirs

@Vladimirs eu só pode pensar margin-top: calc((56px - 16px) / 2), onde 56px - parent height, 16px - element height/font-size- jsFiddle
Vucko

Respostas:


331

Antes de tudo, observe que isso vertical-aligné aplicável apenas às células da tabela e aos elementos no nível de linha.

Existem duas maneiras de obter alinhamentos verticais que podem ou não atender às suas necessidades. No entanto, mostrarei dois métodos dos meus favoritos:

1. Usando transformetop

.valign {
    position: relative;
    top: 50%;
    transform: translateY(-50%);
    /* vendor prefixes omitted due to brevity */
}
<div style="position: absolute; left: 50px; top: 50px;">
    <div style="text-align: left; position: absolute;height: 56px;background-color: pink;">
        <div class="valign" style="background-color: lightblue;">test</div>
    </div>
</div>

O ponto principal é que um valor percentual em topé relativo ao do heightbloco que o contém; Enquanto um valor percentual em transforms é relativo ao tamanho da própria caixa (a caixa delimitadora).

Se você tiver problemas de renderização de fonte (fonte embaçada), a correção será adicionada perspective(1px)à transformdeclaração para que ela se torne:

transform: perspective(1px) translateY(-50%);

Vale notar que o CSS transform é suportado no IE9 + .

2. Usando inline-blockelementos (pseudo-)

Neste método, temos dois inline-blockelementos irmãos que são alinhados verticalmente no meio por vertical-align: middledeclaração.

Um deles tem um heightdos 100%seus pais e o outro é o elemento desejado, que queremos alinhá-lo no meio.

.parent {
    text-align: left;
    position: absolute;
    height: 56px;
    background-color: pink;
    white-space: nowrap;
    font-size: 0; /* remove the gap between inline level elements */
}

.dummy-child { height: 100%; }

.valign {
    font-size: 16px; /* re-set the font-size */
}

.dummy-child, .valign {
    display: inline-block;
    vertical-align: middle;
}
<div style="position: absolute; left: 50px; top: 50px;">
    <div class="parent">
        <div class="dummy-child"></div>
        <div class="valign" style="background-color: lightblue;">test</div>
    </div>
</div>

Por fim, devemos usar um dos métodos disponíveis para remover a lacuna entre os elementos em nível de linha .


Obrigado por estas dicas úteis. Estava trabalhando para o meu projeto. Bom trabalho.
Sedat Kumcu

Para o primeiro valignelemento do método deve serdisplay: block
Oleg

transform: translateY(-50%);Nunca vi isso antes, mas funciona perfeitamente. Poupança da vida real.
Benny Bottema 26/01

55

usa isto :

.Absolute-Center {
    margin: auto;
    position: absolute;
    top: 0; left: 0; bottom: 0; right: 0;
}

consulte este link: https://www.smashingmagazine.com/2013/08/absolute-horizontal-vertical-centering-css/


Como essa não é a solução principal? Tão fácil e funciona!
Mason

21
Lembre-se de que a heightpropriedade deve ser definida (em px, em etc.) para que isso funcione.
quer

E se eu tiver várias divs dentro do pai? não seriam todos colocados um em cima do outro?
Psykid

ele não funciona se não há mais uma criança no mesmo nível com "absoluta-center"
Pascut

18

Use o flex blox em sua div posicionada de maneira distraída para centralizar seu conteúdo.

Veja o exemplo https://plnkr.co/edit/wJIX2NpbNhO34X68ZyoY?p=preview

.some-absolute-div {    
  display: -webkit-box;
  display: -webkit-flex;
  display: -moz-box;
  display: -moz-flex;
  display: -ms-flexbox;
  display: flex;

  -webkit-box-pack: center;
  -ms-flex-pack: center;
  -webkit-justify-content: center;
  -moz-justify-content: center;
  justify-content: center;

  -webkit-box-align: center;
  -ms-flex-align: center;
  -webkit-align-items: center;
  -moz-align-items: center;
  align-items: center;
}

11

Centralizar verticalmente e horizontalmente:

.parent{
  height: 100%;
  position: absolute;
  width: 100%;
  top: 0;
  left: 0;
}
.c{
  position: absolute;
  top: 50%;
  left: 0;
  right: 0;
  transform: translateY(-50%);
}

3

Você pode usar display:table/table-cell;

.a{
   position: absolute; 
  left: 50px; 
  top: 50px;
  display:table;
}
.b{
  text-align: left; 
  display:table-cell;
  height: 56px;
  vertical-align: middle;
  background-color: pink;
}
.c {
  background-color: lightblue;
}
<div class="a">
  <div  class="b">
    <div class="c" >test</div>
  </div>
</div>


Obrigado, seu exemplo funciona perfeitamente, por mais que .bfalte, o position: absolute;que é importante para exibir outras coisas que não foram incluídas para manter o código mais claro. Eu sei que não faz sentido ter a célula de tabela absolutamente posicionada, mas talvez haja outra abordagem que permita reter position: absolute;as classes .ae as .bclasses?
Vladimirs

se a é uma posição absoluta eb (a criança) mede seu tamanho, b está em posição absoluta em relação ao restante do conteúdo. a menos que a deva permanecer sem tamanho, não entendo o propósito do absoluto dentro do absoluto?
G-Cyrillus

1

Aqui está uma maneira simples de usar o objeto Top.

por exemplo: se o tamanho absoluto do elemento for 60px.

.absolute-element { 
    position:absolute; 
    height:60px; 
    top: calc(50% - 60px);
}

2
O uso calcé útil, embora isso deva ser top: calc(50% - 30px)realmente centralizado.
brainbag

1

Uma solução simples adicional

HTML:

<div id="d1">
    <div id="d2">
        Text
    </div>
</div>

CSS:

#d1{
    position:absolute;
    top:100px;left:100px;
}

#d2{
    border:1px solid black;
    height:50px; width:50px;
    display:table-cell;
    vertical-align:middle;
    text-align:center;  
}

0

Verifique esta resposta para um problema semelhante.

Esta é de longe a maneira mais fácil que encontrei.

https://stackoverflow.com/a/26079837/4593442

NOTA. Eu usei display: -webkit-flex; em vez de exibição: flex; para testar dentro do safari.

NOTA DE RODAPÉ. Sou apenas iniciante, compartilhando a ajuda de alguém claramente experiente.


0

Você pode fazer isso usando display:table;div pai e display: table-cell; vertical-align: middle;filho div

<div style="display:table;">
      <div style="text-align: left;  height: 56px;  background-color: pink; display: table-cell; vertical-align: middle;">
          <div style="background-color: lightblue; ">test</div>
      </div>
  </div>


3
é possível que a sua resposta é boa, mas você pode melhorá-lo muito, acrescentando alguns descrição do que seu código faz ...
DaFois
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.