Menu

rem vs em vs px: unidades CSS, porcentagem, vw e vh

rem é relativo ao tamanho de fonte da raiz, em ao tamanho de fonte do elemento atual, px é fixo e % depende da propriedade. Veja cada unidade medida em uma demo aninhada, por que o em se multiplica, quando usar cada uma e como vw, vh e dvh funcionam.

Esta página tem editores executáveis - edite, execute e veja a saída na hora.

rem vs em em uma demo aninhada

rem é relativo ao tamanho de fonte da raiz (o elemento <html>, 16px por padrão). em é relativo ao tamanho de fonte atual, que no caso de font-size é o do pai. Aninhe a mesma classe três vezes e a diferença aparece:

Os tamanhos impressos são o que o navegador calculou. Cada 1.25em multiplica o pai: 20px, depois 25px, depois 31.25px. Cada 1.25rem olha só para a raiz: 20px, 20px, 20px. Essa multiplicação é o motivo de tamanhos de fonte em em saírem do controle em listas e menus aninhados, e de a maioria dos sites definir tamanhos de fonte em rem.

A que cada unidade é relativa

UnidadeRelativa a1 unidade por padrão
pxnada (um pixel CSS)1px
remtamanho de fonte do elemento raiz (html)16px
emtamanho de fonte do elemento; no próprio font-size, o do pai16px no nível mais alto
%depende da propriedade (veja abaixo)
vw / vh1% da largura / altura da viewport
dvh, svh, lvh1% da altura dinâmica, pequena ou grande da viewport
vmin / vmax1% do lado menor / maior da viewport
cha largura do "0" na fonte atualcerca de meio em
exa altura do x na fonte atualcerca de meio em

Um pixel CSS não é um pixel do dispositivo: em um celular com tela 3x, 1px tem 3 pixels do dispositivo de largura. Ele mantém mais ou menos o mesmo tamanho visual entre telas, e é por isso que o px continua bom para bordas e sombras.

em para espaçamentos que acompanham o texto

em não é só para tamanhos de fonte. Em padding, margin, width ou border-radius, ele significa "vezes o tamanho de fonte deste elemento". Isso faz uma única classe de botão funcionar em qualquer tamanho:

O padding de cada botão é metade do tamanho de fonte na vertical e um tamanho de fonte na horizontal, então os três parecem o mesmo botão em três tamanhos. Com padding em px, você precisaria de uma regra de padding para cada tamanho.

Repare que os botões não herdam o tamanho de fonte da página por padrão (os navegadores dão aos controles de formulário um tamanho próprio), então o botão do meio aqui tem 13.33px no Chrome, e não 16px. Acrescente font: inherit a botões e inputs quando quiser que combinem com a página.

Porcentagens: depende da propriedade

% não tem um significado único. Cada propriedade diz do que ela é porcentagem:

Propriedade% é relativo a
width, max-width, left, righta largura do pai (do bloco que o contém)
height, top, bottoma altura do pai, e só se o pai tiver uma altura definida
padding, margin (os quatro lados)a largura do pai
font-sizeo tamanho de fonte do pai (150% = 1.5em)
line-heighto tamanho de fonte do próprio elemento
transform: translate()o tamanho do próprio elemento

width: 50% dá 200px, metade do pai. padding-top: 5% dá 20px: 5% da largura do pai, não da altura. E height: 50% não faz nada, porque o pai não tem altura definida, então o filho só tem a altura do texto mais esse padding. A página de width e height trata dessa regra em detalhe.

vw, vh e a barra de endereço do celular

1vw é 1% da largura da viewport e 1vh 1% da altura. Eles são úteis em seções de tela cheia e em tamanhos fluidos (muitas vezes dentro de clamp()). No celular, o vh tem uma pegadinha: a barra de endereço do navegador entra e sai conforme você rola, e 100vh é a altura sem a barra, então um destaque com height: 100vh fica cortado embaixo quando a barra aparece. As unidades mais novas resolvem isso:

UnidadeAltura usada
100vha viewport grande (barras escondidas) na maioria dos navegadores móveis
100svha viewport pequena (barras visíveis): sempre cabe
100lvha viewport grande, de forma explícita
100dvha viewport dinâmica: muda conforme as barras se movem
.hero {
  min-height: 100vh;  /* fallback for older browsers */
  min-height: 100svh; /* fits the screen even with the address bar visible */
}

O vw tem a própria pegadinha: 100vw inclui a largura de uma barra de rolagem vertical quando ela ocupa espaço (como no Windows), então width: 100vw pode ficar mais largo que a página e criar uma barra de rolagem horizontal. Use width: 100% para "a largura toda do pai".

ch para um comprimento de linha legível

ch é a largura do caractere "0", então max-width: 65ch limita um parágrafo a cerca de 65 caracteres por linha, um comprimento confortável de leitura, em qualquer tamanho de fonte:

Qual unidade usar

ParaUsePor quê
Tamanhos de fonteremConsistente em todo lugar, respeita a configuração de fonte do leitor
Padding e gaps em componentesrem ou emem quando deve crescer com o texto do próprio componente
Bordas, linhas finas, sombraspxDevem continuar finas em qualquer tamanho de fonte
Larguras de layout%, fr, max-width em rem ou chSeguem o contêiner, limitam o comprimento da linha
Seções de tela cheiasvh / dvh (com vh de reserva)Lidam com a barra de endereço do celular
Tipografia fluidaclamp() misturando rem e vwCresce com a tela dentro de limites

Por que o rem respeita os leitores e o px não

Os navegadores têm uma configuração de tamanho de fonte padrão, usada por pessoas que precisam de texto maior. Ela muda o tamanho de fonte da raiz, então tudo em rem e em cresce junto. Um font-size: 14px continua com 14px, seja qual for a escolha do leitor. O zoom do navegador também escala o px, mas é na configuração de tamanho de fonte que muitos leitores se apoiam. Esse é o principal motivo para definir tamanhos de fonte em rem.

Alguns sites definem html { font-size: 62.5%; } para que 1rem valha 10px e a conta fique mais fácil. Isso continua respeitando a configuração do leitor (62.5% do que ele escolheu), mas lembre de definir um font-size legível no body, senão todo elemento sem tamanho próprio mostra texto de 10px.

Erros comuns

  • Tamanhos de fonte em em em elementos aninhados. Eles se multiplicam a cada nível. Use rem nos tamanhos de fonte.
  • height: 50% que não faz nada. O pai precisa de uma altura definida para uma altura em porcentagem funcionar.
  • Esperar que padding-top: 10% siga a altura do pai. Porcentagens de padding e margin verticais usam a largura do pai.
  • width: 100vw criando uma barra de rolagem horizontal. Ele inclui a barra de rolagem. Use 100%.
  • height: 100vh cortado no celular. Use 100svh ou 100dvh.
  • Definir html { font-size: 12px }. Um valor em px na raiz sobrescreve a configuração de fonte do leitor na página toda. Deixe a raiz em paz ou use uma porcentagem.

Perguntas frequentes

Qual a diferença entre rem e em?

rem é relativo ao tamanho de fonte do elemento raiz (<html>), então 1.5rem tem o mesmo tamanho em toda a página. em é relativo ao tamanho de fonte do próprio elemento (no caso de font-size, ao do pai), então se multiplica quando os elementos são aninhados.

Quantos pixels tem 1rem?

16px por padrão, porque os navegadores definem o tamanho de fonte da raiz como 16px. Se o usuário aumentar o tamanho de fonte padrão nas configurações do navegador, ou se você definir html { font-size: ... }, o 1rem muda junto.

Devo usar rem ou px no tamanho da fonte?

Use rem nos tamanhos de fonte. Ele respeita a configuração de tamanho de fonte padrão do leitor no navegador, que o px ignora. O zoom do navegador escala os dois, mas nem todo leitor usa zoom.

Quando usar em em vez de rem?

Use em em espaçamentos que devem acompanhar o texto do próprio elemento, como o padding de um botão ou o tamanho de um ícone ao lado do texto. A mesma classe fica certa em qualquer tamanho de fonte. Use rem nos tamanhos de fonte e nos espaçamentos da página, para nada se multiplicar.

Qual a diferença entre 100vh e 100dvh?

Nos navegadores móveis, 100vh é a altura com a barra de endereço escondida, então uma seção 100vh fica mais alta que a tela visível enquanto a barra aparece. 100dvh (altura dinâmica da viewport) acompanha a barra quando ela aparece e some, e 100svh é sempre a altura menor.

Coddy programming languages illustration

Aprenda a programar com o Coddy

COMEÇAR