O que é melhor: definir valores absolutos ou relativos em CSS?
É claro que depende.
Por exemplo, se John pesa 90kg, não é preciso nenhuma informação a mais para saber seu peso. Pois kg é um valor absoluto.
Agora imagine que Doe pese 85%. Arrisco dizer que a primeira coisa que você pensou foi:
85% de quê? Quantos kg Doe pesa?
Não é possível responder, já que percentual é um valor relativo. E nesse caso você precisa de uma referência.
Se a referência para o peso de Doe for John, posso afirmar que Doe pesa 76,5kg (90 x 0,85 = 76,5).
Agora, se a referência para o peso de Doe for o peso do próprio Doe há 1 ano, o seu peso pode não ser o mesmo.
De forma teórica, absoluto é aquilo que existe por si só, já o relativo precisa de uma referência para existir.
Mas voltando a falar de CSS... eu sempre utilizo:
Valores relativos para propriedades CSS que variam de acordo com alguma variável (como por exemplo o tamanho da janela, o elemento pai ou elemento root)
Valores absolutos para propriedades CSS que não variam
Conforme a W3Schools, existem diversos tipos de medidas absolutas e relativas . Veja agora as mais usadas:
Valores absolutos em CSS
Apesar de você poder usar centímetros e polegadas em propriedades CSS, o mais recomendado (e usado) é pixels mesmo.
Quando um elemento possui width: 800px
, a sua largura nunca será diferente disso. Mesmo que a janela tenha menos do que 800px e crie aquela barra de rolagem lateral que todo front-end ama odiar.
As duas principais vantagens dos valores absolutos em CSS são:
Maior previsibilidade, pois não haverá surpresas em como seu elemento irá renderizar. É aquela medida e pronto
Melhor desempenho, já que o navegador não precisará calcular nada, a medida em pixels já está bem explícita
Mas não pense em trocar os valores relativos do CSS por valores absolutos, para melhorar o desempenho. Caso contrário, cenas como essa seriam comuns:
@media screen and (min-width: 320px) {
.container {
width: 320px;
}
}
@media screen and (min-width: 321px) {
.container {
width: 321px;
}
}
@media screen and (min-width: 322px) {
.container {
width: 322px;
}
}
/* ... */
@media screen and (min-width: 1600px) {
.container {
width: 1600px;
}
}
/* E contando... */
Isso causaria o efeito contrário, tornando o seu código gigante e ineficiente.
Você deve ter percebido que a primeira grande desvantagem de usar valores absolutos é que eles não se adaptam a diferentes cenários. Logo, uma seção com 400px de largura terá essa medida em um iPhone, tablet, notebook e tela ultrawide.
Para evitar isso, você pode usar os valores relativos:
Valores relativos em CSS
Diferente dos valores absolutos, os valores relativos precisam de uma referência para existir.
Exemplo:
<div class="container">
<div class="item">Item 1</div>
<div class="item">Item 2</div>
<div class="item">Item 3</div>
</div>
.container {
width: 800px;
}
.item {
width: 50%;
}
Em CSS, valores percentuais usam como referência o elemento pai. Então, a referência para a largura do .item
é .container
.
Nesse caso, o navegador realiza um cálculo para descobrir que a largura de .item
deve ser 400px:
50% de 800px = 400px
É por isso que todo front-end bate cabeça (eu ainda bato) para fazer funcionar o bendito height: 100%
(e às vezes não funciona). Porque o elemento já possui altura de 100% em relação ao seu elemento pai.
Vou fugir um pouco do assunto, mas valores em percentual (%) não são relativos ao tamanho da janela.
Se você quiser que algo fique da altura da janela, use
height: 100vh
(vh = viewport height)Se você quiser que algo fique da largura da janela, use
width: 100vw
(vw = viewport width)
"Então quer dizer que, quando eu uso um valor relativo, é assim que o navegador carrega aquele elemento?"
É, não é bem assim.
Todo elemento possui um valor absoluto
Como você leu no começo do artigo, valores relativos precisam de uma referência para serem definidos.
Vou continuar no exemplo anterior, digamos que você mude a largura do .container
para 700px:
.container {
width: 700px;
}
.item {
width: 50%;
}
O cálculo é refeito, para descobrir a nova largura de 350px:
50% de 700px = 350px
Mas por que o navegador faz esses cálculos? Essa foi a dúvida que me fez querer escrever esse post. E a resposta encontrei nesse artigo do Google sobre layout .
Basicamente, todas as medidas relativas são convertidas em pixels absolutos na tela.
Isso quer dizer que, mesmo que seu elemento possua um width: 50vw
, ele terá um valor absoluto atrelado a ele. Se sua janela tiver 700px de largura, então o valor absoluto será width: 350px
.
"Mas e se eu redimensionar minha janela para 600px de largura?"
Então seu elemento passará a ter width: 300px
.
Veja a magia acontecendo você mesmo:
O que é melhor: valores absolutos ou relativos?
A resposta simples e direta é: qualquer um, desde que o outro não seja melhor (risos).
Agora sério, é claro que depende.
Ao longo desse texto eu expliquei algumas características tanto de valores absolutos, quanto de relativos.
Basta você adaptar a sua situação a essas características, e a resposta talvez não pareça tão distante.
Vou deixar aqui algumas preferências pessoais (NÃO É REGRA!).
Valores para font-size em CSS
Nessa propriedade, gosto de usar valores em rem
:
html {
font-size: 16px;
}
h1 {
font-size: 3rem; /* 48px */
}
p {
font-size: 1rem; /* 16px */
}
.small {
font-size: 0.8rem; /* 12,8px */
}
1rem
é igual ao font-size
do elemento root (na web, também chamado de tag <html>
). Então para descobrir o valor em pixels, basta multiplicar o valor em rem
pelo font-size
do root.
Deixei comentado no código acima o valor em pixels calculado.
A grande vantagem dessa propriedade é deixar facilitar a responsividade do site. Basta que você altere o tamanho da fonte do elemento root.
Valores para width, height e propriedades de layouts em CSS
Nessas propriedades, sempre dou preferência para usar valores percentuais. Isso porque na maioria dos casos, seu tamanho depende do elemento pai.
Para fazer um modal, overlay e outros elementos posicionados, uso vw
para definir width
e vh
para height
. Isso serve apenas para garantir que o elemento use a totalidade da janela como referência. Mesmo assim, valores percentuais também funcionam.
Em algumas situações, usar a propriedade max-width
e/ou max-height
torna seu código mais dinâmico ainda. Veja um exemplo:
.container {
width: 100%;
max-width: 992px;
}
Isso fará com que o elemento ocupe toda a largura do elemento pai (width: 100%
). Porém quando esse elemento pai for maior do que 992px, ele ficará limitado a esse tamanho (max-width: 992px
).
Isso não torna o elemento necessariamente responsivo, mas às vezes evita o uso Media Queries.
Sem a propriedade max-width
, o elemento ficaria um "chiclete" (aumentaria infinitamente junto com o elemento pai).
Valores para margin e padding em CSS
Esse é outro caso onde o uso da medida em rem
é muito bem vindo.
Isso porque os espaçamentos devem se adequar a diferentes tamanhos de telas. E quando o font-size
do elemento root é atualizado pelas Media Queries, todo o resto se adapta junto.
Outra alternativa ao rem
é definir variáveis do CSS:
:root {
--spacing-small: 5px;
--spacing-medium: 10px;
--spacing-large: 15px;
}
@media screen and (min-width: 768px) {
:root {
--spacing-small: 20px;
--spacing-medium: 25px;
--spacing-large: 35px;
}
}
.container {
padding: var(--spacing-large);
}
.card {
padding: var(--spacing-small);
}
Assim, apesar de usar pixels que são valores fixos, a responsividade não fica tão complicada.
Callback
Acho que fica legal explicar as principais diferenças em uma tabela:
Medidas absolutas (px) | Medidas relativas (%, rem, vw, vh) |
---|---|
Os valores existem por si só | Os valores precisam de uma referência |
Exige menos do navegador (melhor performance) | Exige que o navegador calcule o valor em pixels |
Os valores são mais previsíveis | Os valores gerados no navegador podem gerar algumas surpresas |
Acabei de ler esse artigo que fala sobre acessibilidade em pixel, em e rem e dá dicas de como decidir qual medida usar. A frase chave desse artigo para mim foi:
Esse valor deve aumentar à medida que o usuário aumenta o tamanho da fonte padrão do navegador? Esta questão é a raiz do modelo mental que utilizo. Se o valor aumentar com o tamanho da fonte padrão, eu uso
rem
. Caso contrário, eu usopx
.
Se tiver dúvidas, sugestões ou leu algo que não é bem assim como eu escrevi, pode colocar nos comentários ;)
Obrigado!