CSS

CSS - Altura automática proporcional à largura sem JavaScript

Aprenda a definir elementos com dimensões proporcionais com CSS sem nenhuma linha de JavaScript.

há 4 anos 3 meses

Formação Desenvolvedor HTML e CSS
Conheça a formação em detalhes

Olá Web Developer! Hoje em dia precisamos desenvolver páginas para os mais variados tamanhos de telas. Isso está cada vez mais simples, principalmente com o Flexbox e CSS Grid. Porém, não temos ainda uma propriedade no CSS que nos permite definir a proporção das dimensões de um elemento. Aqui nós aprenderemos como é fácil fazer isso.

Padding com porcentagem

Algo que pode passar despercebido por alguns desenvolvedores é usar porcentagem como valor das propriedades de margem interna (padding).

Quando definimos um valor em porcentagem, estamos querendo que aquele valor seja relativo a um outro valor. Então quando definimos que queremos um width de 50%, estamos dizendo que queremos que ele tenha a metade do valor do width do elemento pai. Se este tiver 200px de largura, o filho com 50% ficará com 100px de largura.

Quando usamos porcentagem no padding, ele não irá pegar a porcentagem relativa ao padding do elemento pai, e sim, proporcional à largura do pai. Veja no exemplo interativo abaixo:

<div class="box-container" >
	<div class="box-content" ></div>
</div>

Note que eu não defini nenhuma altura para .box-container, apenas largura. E no seu elemento filho, .box-content, mandei ele ter altura igual a 0 e coloquei uma porcentagem em padding-bottom (também poderia ser padding-top). Assim, sua dimensão vertical ficará por conta do padding-bottom.

Como dito anteriormente, a propriedade padding utiliza a largura do elemento pai como base para calcular seu valor quando utilizamos porcentagem. Então se colocarmos o pai com width: 200px e o filho tiver padding-bottom: 50%, sua altura será 100px. Como o elemento filho tem sua altura modificada, o elemento pai também terá. Podemos aproveitar isso para criar um container que mantenha as proporções entre largura e altura. Assim, um elemento que tem sua largura modificada pela largura da tela manterá uma altura proporcional.

Teste com outros valores. Um bom exemplo é deixar o padding-bottom com valor 100%. Isso fará com que a altura do elemento filho seja igual à largura do elemento pai, resultando em um quadrado, não importa o quanto a largura do elemento pai seja modificada.

Só um detalhe: eu defini width do .box-container em px apenas para dar um exemplo, mas você pode usar qualquer unidade para a largura do elemento pai, como % ao criar um elemento responsivo para a sua página.

Criando um container reutilizável

Agora que já entendemos o conceito, vamos arrumar esse elemento para que ele seja reutilizável em qualquer projeto. Vamos por partes para entender como ele vai funcionar até chegar em um resultado bem simples e limpo.

Aproveitando pseudo-elementos

Para não ter o trabalho de escrever no HTML um elemento como container que cuidará da largura e um elemento filho apenas com padding-bottom para cuidar da altura, podemos aproveitar os Pseudo-Elementos. Assim criaremos uma única tag e o CSS automaticamente irá inserir o responsável pela altura.

Vamos então remover o box-content e passar suas propriedades para um pseudo-elemento de box-container.

<div class="box-content" ></div>

E nosso CSS está no exemplo abaixo:

Ok, não temos mais uma div vazia, passamos essa função para um pseudo-elemento que já está crescendo, mas o elemento pai não está mais. O pseudo-elemento também não possui mais largura, pois sua dimensão é baseada no seu conteúdo, e definimos content como vazio (““). Mas isso não importa, já que ele é apenas um controlador de altura. O que faremos agora é arrumar para que o elemento pai possa ter sua altura modificada.

Arrumando os pseudo-elementos

A primeira coisa a se notar é que o pseudo-elemento está ocupando espaço. Isso pode atrapalhar o conteúdo que quisermos colocar no nosso container. Um jeito simples para ele não atrapalhar nosso conteúdo é colocar um float.

A propriedade float sempre precisa ser limpada para evitar problemas no layout. Podemos fazer isso usando outro pseudo elemento, que colocaremos no ::before. Como por padrão os pseudo-elementos crescem de acordo com seu conteúdo e aqui também colocamos o content vazio, vamos mudar seu display para block para ele ter um tamanho.

Nosso código ficará assim:

Deixando o elemento reutilizável

Veja que agora temos uma única tag que podemos controlar a altura apenas mudando a sua largura. Mas para que o elemento seja realmente reutilizável, precisamos permitir que o desenvolvedor possa definir qual a proporção daquele elemento. Podemos aproveitar as variáveis CSS. Se você ainda não sabe como usá-las, eu mostro no nosso canal do YouTube no vídeo Variáveis com CSS puro.

Vamos criar uma variável CSS que vai indicar qual a proporção que deve ser mantida. Vamos chamar de aspect-ratio e colocar diretamente na tag. Vamos supor que queremos a mesma proporção de telas widescreen, que é 16:9. Vamos criar a variável com o valor 16/9. Assim poderemos utilizar este valor com a função calc() para calcular a porcentagem, afinal é mais simples de entender 16/9 do que 56.26%, não é mesmo?

<div class="box-content" style="--aspect-ratio: 16/9" ></div>

E o nosso novo padding-bottom está no exemplo abaixo:

Simplificando ainda mais o HTML

O nosso elemento com dimensões proporcionais está pronto. Temos um CSS simples e para utilizar basta criar um elemento com a classe box-content e colocar uma variável aspect-ratio para definir a proporção. Se quiser, você pode parar por aqui mesmo.

Mas se precisamos definir a variável de controle de proporção, não seria mais simples definir estes estilos simplesmente para elementos que possuem essa variável, nos poupando do trabalho de ter que colocar a classe box-content? Podemos fazer isso apenas alterando os seletores.

Vamos trocar o seletor .box-content por [style*="--aspect-ratio"]. Esse seletor basicamente está indicando para pegar os elementos que possuem --aspect-ratio em alguma parte dentro do atributo style.

Veja como nosso HTML ficará bem mais simples:

<div style="--aspect-ratio: 4/3" ></div>
<div style="--aspect-ratio: 16/9" ></div>

E nosso CSS:

Agora você tem um container reutilizável que mantém a proporção entre largura e altura. Para deixá-lo responsivo, basta deixar seu width como 100%. Assim ele mudará de tamanho de acordo com o seu elemento pai.

Autor(a) do artigo

Akira Hanashiro
Akira Hanashiro

Graduado em Análise e Desenvolvimento de Sistemas, Pós-graduado em Projetos e Desenvolvimento de Aplicações Web e MBA em Machine Learning. Especializado em Front End e curte desenvolvimento de jogos.

Todos os artigos

Artigos relacionados Ver todos