Uma das declarações CSS campeã, senão a campeã absoluta, de reclamações de iniciantes (e até de alguns com alguma prática em CSS) é a declaração: height: 100%;. É muito comum encontrar 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 se trata 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 o 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 comwidth: 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? Por padrão, a largura é 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.
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, 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.
Se não sabia, agora você já sabe porque height: 100% “não funciona”!
***
Oferta exclusiva para os leitores iMasters deste artigo: todos os livros do Maujor com 25% de desconto no site da Novatec Editora! Insira o código promocional maujor25 no carrinho de compras para gerar o desconto. (Válido até 04/06/2013)