Categories: CSStodas

Por que height: 100% não funciona?

Uma das declarações CSS campeã, senão a campeã absoluta, das reclamações de iniciantes (e até de alguns com alguma prática em CSS) é a declaração: height: 100%;.
É muito comum encontrar-se em fóruns, listas de discussão e redes sociais perguntas do tipo:

“Já declarei height: 100% na minha CSS e o div não estende verticalmente como ‘era de se esperar’. Alguma dica?”.

ou respostas do tipo:

“Declara height: 100% e o div fica responsivo na vertical.”

O problema não é com o funcionamento da propriedade, pois ela foi criada para estender a altura de um box exatamente 100% como, realmente, era de se esperar.

Então, o que há de errado?
Nada há de errado, mas antes de mais nada é preciso entender como funciona a propriedade height.

É sabido que a medida CSS (ou qualquer medida) expressa em porcentagem precisa de uma referência para ser calculada, pois trata-se de uma medida relativa, ou seja, tomada em relação a alguma coisa.

width: 100%

No Box Model CSS um box tem sua largura inicial (width) definida como auto que por padrão é tomada como sendo toda a largura da viewport. Se o usuário redimensiona a janela do navegador altera dinamicamente a largura da viewport e em consequência a largura auto do box para um valor conhecido igual a largura atual da viewport (tantos pixels, por exemplo). É importante notar que o valor auto para a largura de um box é um valor perfeitamente determinado e conhecido, igual a largura da viewport.

A referência para cálculo da largura, expressa em porcentagem, de um box, é a largura do seu elemento-pai. Assim, um box com width: 50% que seja filho de um container com width: 200px, possui uma largura igual a 50% de 200px = 100px. Elementar e fácil!

E, se a largura do elemento-pai não for definida? Como é feito o cálculo?

Se a largura do elemento-pai não for definida explicitamente ela é, por padrão, tomada como auto.

E, se não houver elemento ancestral com largura definida?

Nesse caso, está implícito que a largura de todos os ancestrais é auto, ou seja a referência para cálculo da porcentagem é a largura da viewport, pois como já dissemos, para a propriedade width o valor auto é igual a largura da viewport.

Nessas condições um box com largura de 25% (width: 25%) ocupará sempre 1/4 da largura da viewport. Se o usuário redimensiona a janela a largura se ajusta dinamicamente.

height: 100%

No Box Model CSS um box tem sua altura inicial (height) definida como auto e, ao contrário da propriedade width, por padrão NÃO é tomada como sendo toda a altura da viewport. Para a propriedade height o valor auto, por padrão, é tomado como aquele necessário para acomodar verticalmente o conteúdo e depende de outros fatores como, por exemplo, a largura do box.

A referência para cálculo da altura, expressa em porcentagem, de um box, é a altura do seu elemento-pai. Assim, um box com height: 50% que seja filho de um container com height: 200px, possui uma altura igual a 50% de 200px = 100px. Elementar e fácil!

E, se a altura do elemento-pai não for definida? Como é feito o cálculo?

Nesse caso, está implícito que a altura do elemento-pai é auto (indefinido) e qualquer porcentagem de indefinido resulta em indefinido. A declaração CSS não é aplicada e quem determina a altura é o conteúdo. Eis porque height: 100% não funciona.

Fazendo height: 100% funcionar

Considere a teoria explicada e não esqueça que os elementos html e body são os ancestrais mais distantes de qualquer elemento no documento.

Em qualquer estrutura HTML ao definirmos a altura de um elemento em porcentagem é necessário que seu elemento-pai tenha sua altura definida. Se a altura definida para o elemento-pai for em medida absoluta a porcentagem é tomada em relação a essa medida e fim de papo.

Contudo se a altura do elemento-pai for definida em porcentagem, é preciso examinar a definição da altura do ancestral (elemento-pai do elemento-pai), repetindo-se o processo até chegar ao elemento raiz html.

Se nessa cadeia de ancestrais qualquer um deles não tiver sua altura definida, as definições de altura em porcentagem para todos os seus descendentes não são consideradas, pois como vimos anteriormente não definir altura equivale ao valor auto para ela (que é indefinido). Eis porque height: 100% não funciona.

Exemplos

Para demonstrar o funcioanamento da declaração height: 100% conforme a teoria relatada nessa matéria criei páginas de exemplos:

As páginas mostram um elemento div com a classe um (div.um) e respectivo conteúdo, ao qual pretendemos estender a altura por toda a altura da viewport.
A primeira tentativa é simplesmente declarar a regra de estilo: .um { height: 100%; }. Não vai funcionar, pois o elemento-pai do div.um (body) não tem sua altura declarada.
Ver Exemplo 1 (abre em nova janela).

Para funcionar precisamos declarar a altura de TODOS os elementos ancestrais de div.um. São eles: body e html.
Ver Exemplo 2 (abre em nova janela).

Talvez você seja tentado a declarar: * { height: 100%; } na esperança de normatizar alturas. Ou ainda, declarar height: 100%; para todos os elementos de um trecho do DOM onde irá precisar de altura estendida. Tal procedimento poderá causar a maior confusão no seu layout.

Se um elemento ao qual se pretende declarar height: 100% contiver margens e/ou paddings verticais na renderização final irá aparecer barra de rolagem vertical, pois o cálculo da porcentagem se faz primeiro e depois são acrescidas as margens e/ou paddings.
Ver Exemplo 3 (abre em nova janela). Observe a barra de rolagem no navegador.

Para eliminar as barras de rolagem devemos subtrair o valor total das margens e/ou paddings verticais de 100%. Caso aqueles espaçamentos sejam definidos em porcentagem simplesmente diminuá-os de 100%, caso em outra unidade de medida use a função calc() das CSS (abre em nova janela).
Ver Exemplo 4 (abre em nova janela). Observe a ausência de barra de rolagem no navegador.

Atualização: Conforme apontado pelo James Clébio no comentário no. 7 podemos usar a propriedade box-sizing em lugar da função calc().

Conclusão

Fazer funcionar height: 100% para um box é fácil, basta declarar explicitamente (não pode ser auto) o valor da altura de TODOS os elementos ancestrais. Difícil é tratar as implicações que isso poderá acarretar para o layout.

Assim, declarar height: 100% é de uso restrito a uns poucos casos particulares e, definitivamente, não é a solução para todos os seus problemas de altura CSS.

Mas, nem tudo está perdido. As especificações para CSS Flexible Box Layout Module já se encontra na fase de Candidata a Recomendação. Entre as funcionalidades dessa especificação destacamos aquelas que permitem um maior controle sobre as dimensões de um box sem dependências com elementos a ele relacionados na marcação.

Atualização em 24/07/2015: (Merci @johnnybegood_21) A especificação do W3C denominada CSS Values and Units Module Level 3 já se encontra na fase de Candidata a Recomendação. Entre as funcionalidades daquela especificação estão previstas as unidades de medidas cujo valor é uma porcentagem da largura ou da altura da viewport (mais informações em Viewport-percentage lengths: the ‘vw’, ‘vh’, ‘vmin’, ‘vmax’ units).

Essa unidade de medida é bem suportada nos navegadores atuais.
Ver Exemplo 5 (abre em nova janela).

Este tutorial foi traduzido para o francês por @pierrechoffe.

Se não sabia, agora você já sabe porque height: 100% “não funciona”!

Maujor

View Comments

  • Cara, pela primeira vez na minha vida eu li um post.
    E valeu a pena!

    Muito obrigado mesmo, a explicação foi excelente.
    Eu não imaginava que seria tão simples de fazer uma div height 100%.

  • Maravilhoso!
    2017 e esse post me ajudou.

    Muito obrigado, amigo! ;))

  • Obrigado Maujor :) eu adorei esse tutorial estou lendo todo esse site com conteúdos muito bem explicados e com boa informações.

  • ...ou pode simplesmente usar o vw/vh (visual width,visual height) que simplesmente pega o tamanho do viewport sem nenhuma dependência, sendo que height:100vh corresponde ao tamanho total da tela (do mesmo jeito que esperam que height:100% funcione).

  • Maravilha! - Ótimo tutorial sobre algo que sempre me deu dor de cabeça! - Obrigado

  • Top!

    usei a unidade vh e matou um problemão que estava passando.

  • Para nao usar o calc()
    basta por na DIV a propriedade box-sizing: border-box;
    o padding ira se aplicado no interior da DIV e nao fora

Share
Published by
Maujor

Recent Posts

Teste seu conhecimento #20

Em 2006 comecei a publicar nesse blog uma série de desafios CSS que consistiam em…

7 anos ago

Teste seu conhecimento #19

Há muito tempo que eu não publico um "Teste seu conhecimento". Esta semana, revendo algumas…

9 anos ago

JavaScript bubbling e capturing

Introdução Elementos da marcação HTML podem ser aninhados uns dentro de outros, criando-se uma cadeia…

10 anos ago

HTML5 – W3C versus WHATWG

HTML5? Web universal? É comum eu me deparar com dúvidas sobre a HTML5 não só…

10 anos ago

Seria esse o futuro das imagens responsivas?

Quem é Tab Atkins Jr? Tab Atkins Jr, um desenvolvedor americano, trabalhou durante muitos anos…

10 anos ago

BrazilJS Conf 2013

Pessoal, a BrazilJS Conf 2013 disponibilizou para o Maujor cupons de desconto para serem oferecidos…

11 anos ago