altura da linha como uma porcentagem não funciona


87

Estou tendo um problema com a altura da linha que não consigo entender.

O código a seguir centralizará uma imagem em um div:

CSS

.bar {
    height: 800px;
    width: 100%;
    line-height:800px;
    background-color: #000;
    text-align: center; 
}

.bar img {
    vertical-align: middle;   
}

HTML

<div class="bar">
    <img src="http://27.media.tumblr.com/yHWA4oxH870ulxnoH7CkOSDR_500.jpg" alt="Foo Image" />
</div>

No entanto, se eu alterar a altura da linha para 100%, a altura da linha não terá efeito (ou pelo menos não se tornará 100% da div).

Exemplo de jsfiddle

Alguém sabe o que estou fazendo de errado?

Respostas:


194

line-height: 100%significa 100% do tamanho da fonte para esse elemento, não 100% de sua altura. Na verdade, a linha de altura é sempre relativa ao tamanho de fonte, não a altura, a menos que o seu valor utiliza uma unidade de comprimento absoluto ( px, pt, etc.).


3
Ah. São sempre os erros bobos que me pegam. Obrigado! Aceitarei sua resposta quando permitir.
— Minha cabeça dói

1
Aparentemente, os autores das especificações pensaram erroneamente que ninguém iria querer definir o tamanho da fonte / altura da linha em relação à altura do elemento ...
— Andy

1
@Andy: A boa (?) Notícia é que em breve isso será possível com o uso de variáveis ​​em cascata . Apenas alguns anos de espera ...
— BoltClock

@BoltClock ah, legal! Isso vai ser bom. Obrigado por me avisar!
— Andy

vh é uma exceção. No CSS3, se você definir como 100vh, ele funcionará como alguns desenvolvedores podem querer. Observe, porém, que ele não funciona em navegadores mais antigos que não suportam CSS3.
— Philll_t

97

Sei que essa pergunta é antiga, mas descobri qual é a solução alternativa perfeita para mim.

Eu adiciono este css ao div que desejo centralizar:

div:before {
  content: "";
  display: inline-block;
  height: 100%;
  vertical-align: middle;
}

Isso funciona sempre e é limpo.

Edit: Apenas para fins de conclusão, eu uso scss e tenho um mixin útil que incluo em todos os pais que são filhos diretos que desejo centralizar verticalmente:

@mixin vertical-align($align: middle) {
  &:before {
    content: "";
    display: inline-block;
    height: 100%;
    vertical-align: $align;
    // you can add font-size 0 here and restore in the children to prevent
    // the inline-block white-space to mess the width of your elements
    font-size: 0;
  }
  & > * {
    vertical-align: $align;
    // although you need to know the font-size, because "inherit" is 0
    font-size: 14px;
  }
}

Explicação completa: div:beforeadicionará um elemento dentro do div, mas antes de qualquer um de seus filhos. Ao usar :beforeou :afterdevemos usar uma content:declaração, caso contrário, nada acontecerá, mas para o nosso propósito, o conteúdo pode estar vazio. Em seguida, dizemos ao elemento para ser tão alto quanto seu pai, desde que a altura de seu pai seja definida e este elemento seja pelo menos inline-block. vertical-aligndefine a posição vertical de self em relação aos pais, ao contrário de text-alignque funciona de maneira diferente.

A @mixindeclaração é para usuários sass e seria usada assim:

div {
    @include vertical-align(middle)
}

Embora as outras respostas estejam todas corretas, esta é provavelmente a solução mais limpa e elegante para o problema acima.
— mstation

Não é a resposta, mas muito útil!
— Alex

Você poderia explicar o que está acontecendo lá em detalhes? Não consigo entender
— Valdrinium

1
@Valdrinit vou editar a resposta com mais explicações
— santiago arizti

36

Quando você usa a porcentagem como a altura da linha, ela não se baseia no contêiner div, mas sim no tamanho da fonte.


22

line-height: 100% seria uma maneira fácil de centralizar verticalmente os elementos, se fosse calculado em relação ao container, mas seria muito fácil, portanto não funciona.

Em vez disso, é apenas outra maneira de dizer a altura da linha: 1em (certo?)

Outra maneira de centralizar verticalmente um elemento seria:

.container {
     position:relative;
}
.center {
     position:absolute;
     top:0; left:0; bottom:0; right:0;
     margin: auto;
     /* for horiz left-align, try "margin: auto auto auto 0" */
}

1
Isso não funciona para mim ... não tenho certeza se estou faltando alguma coisa.
— clifgriffin

1
@clifgriffin, tente definir uma largura e altura fixas tanto no contêiner quanto no filho "central", certificando-se de que o filho seja menor que o contêiner. A criança deve acabar centralizada horizontalmente e verticalmente dentro do recipiente.
— Rolf

22
isso seria muito fácil, portanto, não funciona +1 :-)
— elipoultorak

@clifgriffin certifique-se de que o contêiner tenha a largura e altura corretas, você pode centralizar tudo em uma div do mesmo tamanho. Este foi o ajuste que tive que fazer.
— David Carrigan

@ user3576887 "isso seria muito fácil, portanto, não funciona" é exatamente por que estou rejeitando isso - há uma boa razão para que não funcione da maneira que você gostaria aqui, e isso não deveria ser obscurecido para fins de entretenimento, crítica ou o que quer que seja.
— TheThirdMan

11

pode não ser bonito, mas está funcionando e sua semântica;

<div class="bar" style="display: table; text-align: center;">
    <img style="display: table-cell; vertical-align: middle;" src="http://27.media.tumblr.com/yHWA4oxH870ulxnoH7CkOSDR_500.jpg" alt="Foo Image" />
</div>

display: table-cell dá a um elemento a capacidade única de alinhar verticalmente (pelo menos eu acho que é único)


Obrigado pela resposta, tentei seu código, mas não parece funcionar para mim.
— Minha cabeça dói

hmm, isso é um pouco estranho; se você puder postar parte do seu código para que eu possa dar uma olhada mais de perto, talvez eu possa ajudar mais
— Johan Olsson

Olsson - Acabei de colar seu código em um JSFiddle e não funcionou. Obrigado pela oferta de ajuda - mas posso me safar definindo uma altura de linha absoluta por enquanto. Se isso mudar, analisarei mais detalhadamente sua resposta. Obrigado novamente pela ajuda!
— Minha cabeça dói

6

Essa é uma resposta muito tardia, no entanto, em navegadores modernos, supondo que o elemento pai também tenha 100% da altura da tela, você pode usar a vhunidade da janela de visualização. FIDDLE

line-height: 100vh;

Suporte de navegador


Um uso legítimo raro de vh em vez de%.
— cytsunny de

1

Esta solução funciona no IE9 e superior. Primeiro, definimos a posição superior da criança em 50% (meio do pai). Então, usando uma translateregra, mude a criança para cima pela metade de sua altura real. O principal benefício é que não precisamos definir a altura da criança, ela é calculada dinamicamente pelo navegador. JSFiddle

.bar {
    height: 500px;
    text-align: center;
    background: green;
}
.bar img {
    position: relative;
    top: 50%;
    transform: translate(0, -50%);
}

1

Uma abordagem mais moderna é usar o flexbox para isso, é mais simples e limpo. No entanto, flexbox é um paradigma completamente diferente do que inline-block, floatou positioncostumava ser.

Para alinhar os itens dentro de .parentvocê, faça:

.parent {
  display: flex;
  align-items: center;
}

Isso é tudo. Filhos de flexpais são automaticamente convertidos em itens filhos flexíveis.

Você deve ler mais sobre o flexbox, um bom lugar para começar é esta folha de dicas: https://css-tricks.com/snippets/css/a-guide-to-flexbox/


0

Você pode definir a altura da linha com base na altura desse elemento. Se a altura do elemento 200px significa que você precisa definir a altura da linha para 200px para centralizar o texto.

span {
  height: 200px;
  width: 200px; 
  border: 1px solid black;
  line-height: 200px; 
  display: block;
}
<span>Im vertically center</span>

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.