Valores absolutos e relativos em CSS: quando usar px, % e rem

Entenda as melhores situações no CSS para usar valores absolutos, como pixel, e valores relativos, como percentual ou rem.

  • valor absoluto
  • valor relativo
  • pixel
  • rem
  • css
  • unidade de medida
  • percentual
  • width
  • height
Front-end

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.

Um ovo branco grande ao lado de um ovo marrom pequeno, mostrando que tamanho é algo relativo por comparação
Você percebe que só pode afirmar que o ovo branco é maior, porque o ovo marrom está perto para comparação?

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.

Blocos de cores vermelho, verde e azul representando os pixels na tela
Pixels e RGB

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 navegador recalculando a largura de uma div em pixel, conforme muda o tamanho da janela, mesmo que o width tenha sido definido em vw
O navegador sempre calcula o valor absoluto em pixels

O que é melhor: valores absolutos ou relativos?

A resposta simples e direta é: qualquer um, desde que o outro não seja melhor (risos).

Escrita "laugh" em letra neon (risada em inglês)
Humor e piadas

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:

Valores absolutos e relativos em CSS
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íveisOs 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 uso px.

Josh W Comeau

Se tiver dúvidas, sugestões ou leu algo que não é bem assim como eu escrevi, pode colocar nos comentários ;)

Obrigado!

Veja outros posts sobre Front-end