Sabe aquele mosaico bonito de elementos criado pelo design onde cada coisa tem sua devida proporção, não importa qual é o tamanho da tela do usuário?
E aquela <div>
que você tem que manter em 480x360 a todo custo pro layout funcionar?
Casos assim não são tão frequentes, mas quando aparecem costumam dar um certo trabalho.
O objetivo deste artigo é ensinar a como lidar com elementos que devem permanecer proporcionais o tempo todo.
Aqui estão alguns exemplos:
Para entendermos onde queremos chegar, vou pegar como exemplo a criação de um elemento com a proporção 4:3.
Vou chamar este elemento de panel
e criá-lo dentro de um container
:
1<div class="container"> 2 <div class="panel"></div> 3</div>
Vou também limitar a largura do container a 50%
, centralizá-lo na tela e colocar uma cor vermelha no painel, assim podemos visualizá-lo:
1.container { 2 width: 50%; 3 position: absolute; 4 top: 50%; 5 left: 50%; 6 transform: translate(-50%, -50%); 7} 8 9.panel { 10 background-color: red; 11}
Abordagem 1
Digamos que eu tenha um elemento com 400px
de largura, e quero que ele seja proporcional. Para isso, fazemos uma regra de 3 simples:
400px | -> | 4 |
x | -> | 3 |
Legal, temos a largura e a altura, bora atribuir os valores (vou adicionar também margin: 0 auto;
pra centralizar o painel).
1.panel { 2 background-color: red; 3 width: 400px; 4 height: 300px; 5 margin: 0 auto; 6}
Então temos:
Problema!
A abordagem 1 é bem direta e funciona bem se precisamos de um elemento com dimensões fixas, mas e se o usuário está visualizando no celular? Com dimensões fixas, provavelmente irá aparecer um scroll para que ele consiga ver o elemento inteiro.
Podemos adicionar media queries para alterar esses valores dependendo da resolução do usuário, mas conseguimos fazer melhor que isso, vamos à próxima abordagem.
Abordagem 2
E se ao invés de usarmos valores fixos para as dimensões, usássemos porcentagens? Assim garantimos que nenhum scroll vai aparecer, já que o tamanho do elemento se manterá proporcional ao tamanho da tela, certo? Vamos tentar.
Digamos que queremos um elemento com 100% da largura do seu elemento pai. Fazendo uma regra de 3 novamente:
100% | -> | 4 |
x | -> | 3 |
Agora atribuímos width: 100%;
e height: 75%;
e está resolvido. ERRADO!
Isso está errado por causa da forma como a propriedade height
funciona com porcentagens no CSS.
Segundo a documentação:
Ou seja, se o elemento usando a propriedade height
com porcentagem não tiver um pai que tenha a altura devidamente especificada (ex: px
, rem
, em
, ou outra unidade que não seja porcentagem), ou que esteja posicionado usando position: absolute;
, ela é computada para o valor auto
e a porcentagem atribuída é ignorada.
Problema!
Na abordagem 2, temos que atribuir um valor fixo para o elemento pai, e aí o filho usando um height
com porcentagem vai ter sua altura proporcional a altura fixa do pai, perdendo todo o sentido de se usar a porcentagem e voltando para o problema da abordagem 1.
Então como atribuímos porcentagem ao elemento de uma forma que a altura fique proporcional a qualquer largura que a gente possa querer?
Abordagem 3
Sem mais rodeios, o pulo do gato aqui é usar a propriedade padding
com porcentagem!
Segundo a documentação:
"Porcentagens são referentes a largura do bloco contendo o elemento", perfeito! É disso que precisamos.
Então atribuímos width: 100%;
e padding-top: 75%;
:
1.panel { 2 background-color: red; 3 width: 100%; 4 padding-top: 75%; 5}
E temos:
Resolvido!
padding-top
, mas poderia ter usado também o padding-bottom
, tanto faz. A mágica só acontece porque o tamanho de qualquer padding em porcentagem sempre se refere a largura do elemento.Refinando a solução
O elemento está criado, é proporcional e responsivo, mas há algumas melhorias que ainda podemos fazer:
Sem contas na mão!
Ao invés de fazer as contas manualmente, podemos usar a função calc()
do CSS para fazer isso por nós. Alterando o código:
1.panel { 2 background-color: red; 3 width: 100%; 4 padding-top: calc((3 / 4) * 100%); 5}
Inserindo conteúdo
Você deve ter percebido que se quisermos inserir conteúdo no painel, a proporção será perdida, pois qualquer coisa dentro de <div class="panel"></div>
será inserida considerando o espaçamento do padding.
Para resolver esse problema, podemos simplesmente alterar o painel para que ele tenha um posicionamento relativo, e seu conteúdo tenha um posicionamento absoluto, assim o conteúdo fica sobreposto e não sofre ação do padding.
HTML:
1<div class="container"> 2 <div class="panel"> 3 <div class="content">Conteúdo vem aqui</div> 4 </div> 5</div>
CSS:
1.panel { 2 background-color: red; 3 width: 100%; 4 padding-top: calc((3 / 4) * 100%); 5 position: relative; 6} 7 8.content { 9 position: absolute; 10 top: 0; 11 right: 0; 12 bottom: 0; 13 left: 0; 14}
Fico por aqui e espero que tenha curtido as dicas. Até a próxima!
‘‘Aja antes de falar e, portanto, fale de acordo com os seus atos.— Confúcio