PX vs REM vs EM: o guia completo de unidades CSS
A resposta curta para px vs rem vs em: use rem para quase todo dimensionamento (tamanhos de fonte, padding, margens, gaps, border-radius e breakpoints), porque ele acompanha a configuração de tamanho de fonte do navegador do leitor. Use px para as poucas coisas que nunca devem escalar, como uma borda de 1px ou um deslocamento preciso de sombra. Use em para o caso local raro em que um valor deve crescer junto com o tamanho de fonte do próprio elemento, como o padding de um botão que acompanha o texto dele.
Essa regra cobre 90% das decisões. Os outros 10% são onde mora o problema: a matemática do em composto que pega todo mundo de surpresa na primeira vez, o bug de media query que quebra layouts no zoom e os casos em que px é, na verdade, a escolha mais acessível. Este guia percorre os três pontos, com CSS pronto para rodar em cada um, mais um guia rápido por propriedade que você pode deixar aberto enquanto escreve seus estilos.
O que px, rem e em realmente significam
Cada unidade tem um ponto de referência diferente, e é nisso que a distinção se resume.
px é uma unidade absoluta. Um px é um pixel CSS, e ele mantém esse tamanho não importa o que esteja ao redor. border: 1px solid é um pixel, ponto final. “Absoluto” também significa que ele ignora as preferências do usuário, e mais adiante explico por que isso importa.
rem é relativo ao tamanho de fonte do elemento raiz. A raiz é o <html>, e os navegadores definem seu tamanho de fonte como 16px por padrão. Então 1rem equivale a 16px em uma configuração comum, em toda a página, independentemente do aninhamento. Essa consistência é todo o apelo: um único valor de âncora, sem surpresas.
em é relativo ao tamanho de fonte do elemento atual (ou do seu pai, para propriedades que não sejam font-size). Como essa referência muda à medida que você aninha elementos, os valores em em variam conforme o contexto. O mesmo 1.5em pode resultar em 24px num lugar e 30px em outro.
A âncora que vale a pena decorar é 16px = 1rem. Se você não guardar mais nada, guarde isso. Quando precisar traduzir um valor específico, o conversor de px para rem faz a divisão contra a base que você escolher.
px vs rem vs em num relance
| Unidade | Relativa a | Escala com o tamanho de fonte do usuário? | Uso típico | Comportamento ao aninhar |
|---|---|---|---|---|
px | Nada (absoluta) | Não | Bordas, deslocamentos de sombra, linhas finas | Sempre do mesmo tamanho |
rem | Tamanho de fonte da raiz <html> | Sim | Tamanho de fonte, espaçamento, breakpoints | Sempre do mesmo tamanho |
em | Tamanho de fonte do elemento atual | Sim | Valores locais ligados a um componente | Compõe, pode derivar |
As duas colunas que decidem a maioria das discussões são “escala com o tamanho de fonte do usuário” e “comportamento ao aninhar”. O rem ganha nas duas: respeita a preferência do leitor e permanece previsível. O em compartilha o primeiro benefício, mas abre mão do segundo.
Como cada unidade é calculada
A matemática é aritmética pura. O que confunde as pessoas é por qual número você divide ou multiplica.
rem usa o tamanho de fonte da raiz:
rem = px ÷ tamanho-de-fonte-da-raiz
Com a raiz padrão de 16px, 24px ÷ 16 = 1.5rem. Para voltar, multiplique: 1.5rem × 16 = 24px. Todo rem da página usa esse mesmo 16 (ou o valor que você definir para a raiz), e é exatamente por isso que rem é previsível.
em usa o tamanho de fonte do próprio elemento atual:
em = px ÷ tamanho-de-fonte-do-elemento-atual
Se o font-size de um elemento é 20px, então 1em nesse elemento é 20px, 0.5em é 10px e um padding de 1.5em é 30px. Mude o tamanho de fonte do elemento e cada valor em em ligado a ele muda junto. Esse acoplamento local é o propósito do em, e também a sua armadilha.
A armadilha do em composto
Quando você aninha elementos que usam em para o tamanho de fonte, os valores se multiplicam árvore abaixo. Cada nível herda o tamanho de fonte computado do seu pai e aplica o próprio fator em por cima.
.menu { font-size: 1.2em; } /* o pai tem 16px → 19.2px */
.menu .item { font-size: 1.2em; } /* o pai tem 19.2px → 23.04px */
.menu .item .sub { font-size: 1.2em; } /* o pai tem 23.04px → 27.648px */
Cada nível é “120% do seu pai”, o que parece inofensivo. Mas como o pai já cresceu, o terceiro nível é 1.2 × 1.2 × 1.2 = 1.728em em relação ao 16px original, cerca de 27.6px, não os 19.2px que você poderia ter lido da regra isoladamente. Aninhe uma lista dentro de uma lista dentro de um componente e o texto incha de um jeito difícil de rastrear.
O rem evita isso por completo. 1.2rem é 19.2px quer esteja no topo do documento, quer esteja doze níveis abaixo, porque ele sempre mede contra a raiz, nunca contra o pai. Quando um valor resulta num tamanho que você não esperava, a primeira pergunta a fazer é se ele é em (relativo ao pai, compõe) ou rem (relativo à raiz, estável). Se você está depurando um rem solto e quer ver o tamanho em pixels rápido, o conversor de rem para px resolve na hora.
Quando usar rem
Recorra ao rem por padrão. É a unidade certa para tamanhos de fonte, padding, margens, gaps, border-radius e breakpoints de media query, ou seja, qualquer coisa que deva escalar quando o leitor ajusta o tamanho do texto.
Essa última frase é o argumento de acessibilidade, e ele não é hipotético. As pesquisas da WebAIM com usuários de leitor de tela e baixa visão encontram, de forma consistente, que uma fatia grande dos usuários ajusta o tamanho de fonte padrão do navegador ou do sistema, muitos deles bem acima dos 16px padrão. Um layout dimensionado em rem honra essa mudança: aumente o padrão para 20px e cada valor baseado em rem cresce proporcionalmente. Um layout dimensionado em px a ignora por completo, e o texto fica preso no seu tamanho fixo, por mais que o leitor precise dele maior.
:root {
font-size: 16px; /* 1rem = 16px */
}
h1 { font-size: 2rem; } /* 32px, escala com a preferência do usuário */
p { font-size: 1rem; } /* 16px */
.card { padding: 1.5rem; } /* 24px */
.card { border-radius: 0.5rem; } /* 8px */
Como cada valor aqui está ancorado à mesma raiz, uma única mudança no tamanho de fonte da raiz redimensiona toda a interface na mesma proporção. É isso também que mantém um design system coerente: espaçamento e tipografia se movem juntos em vez de se afastarem.
O truque dos 62.5%
Existe um atalho popular para tornar a aritmética de rem trivial. Defina o tamanho de fonte da raiz como 62.5%, que dá 62.5% × 16px = 10px:
html {
font-size: 62.5%; /* agora 1rem = 10px */
}
body {
font-size: 1.6rem; /* restaura o texto do corpo legível em 16px */
}
h1 { font-size: 2.4rem; } /* 24px */
p { font-size: 1.6rem; } /* 16px */
Com uma raiz de 10px, a conta mental se reduz a “dividir o valor em pixels por 10”: 24px → 2.4rem, 12px → 1.2rem. O único detalhe é restaurar um tamanho de corpo legível com body { font-size: 1.6rem }, já que uma base bruta de 10px deixa o texto padrão pequeno demais. Usar 62.5% como porcentagem em vez de 10px mantém tudo relativo, então um leitor que aumenta o padrão do navegador ainda recebe crescimento proporcional. Se você adotar essa base, configure o tamanho de fonte da raiz no conversor para 10, para que ele combine com a sua folha de estilos.
Quando usar em
Use em quando quiser que um valor escale com o tamanho de fonte do próprio elemento, não da raiz. O caso clássico é um botão:
.btn {
font-size: 1rem; /* dimensionado contra a raiz */
padding: 0.75em 1.5em; /* o padding acompanha o texto do botão */
}
.btn--large {
font-size: 1.25rem; /* uma mudança redimensiona tudo */
}
Como o padding está em em, o modificador .btn--large redimensiona o texto e o padding juntos a partir de uma única declaração, e o botão fica proporcional em qualquer tamanho. A mesma lógica vale para um ícone dimensionado em em para combinar com a linha de texto em que está, ou para um letter-spacing que deve crescer junto com a fonte.
A estratégia que funciona na prática é rem para o esqueleto global, em para as proporções locais. Defina o tamanho de fonte em rem para que ele responda à raiz e à preferência do usuário; defina em em o punhado de valores que devem acompanhar aquele elemento. Só mantenha o em longe de qualquer coisa que aninhe profundamente, ou a armadilha do composto lá de cima volta a se infiltrar.
Quando usar px
Alguns valores realmente não devem escalar, e o px é correto para eles: uma borda de linha fina de 1px, um deslocamento preciso de box-shadow, um anel de foco de 2px. São detalhes de renderização, não conteúdo. Uma borda que “escala” para 1.25px quando o usuário aumenta o texto não ganha nada e pode renderizar como uma linha borrada. O px a mantém nítida.
.divider { border-bottom: 1px solid; } /* deve continuar em 1px */
.card { box-shadow: 0 2px 4px rgba(0,0,0,0.1); } /* deslocamento fixo */
.input:focus { outline: 2px solid; } /* anel de foco nítido */
Quando px é mais acessível
A maioria dos conselhos do tipo “sempre use rem” ignora esta parte contraintuitiva. A escolha acessível não é “rem em tudo”, e sim “escale o que deve escalar, fixe o que não deve”.
Uma borda de 1px é um detalhe fixo. Forçá-la em rem para que cresça quando o usuário aumenta o texto não ajuda na legibilidade; só deixa uma linha fina borrada. Para essas propriedades, px é a escolha mais acessível justamente porque permanece no lugar.
O erro que as pessoas costumam cometer é o inverso: usar px para as coisas que deveriam responder, como tamanhos de fonte e breakpoints. É aí que o px prejudica a acessibilidade. A regra, portanto, é sobre a propriedade, não sobre a unidade. Pergunte se o valor é conteúdo com o qual o leitor interage (escale, rem) ou um detalhe fixo de renderização (fixe, px). A unidade decorre da resposta.
A armadilha das media queries
Esta quebra layouts de verdade e quase nenhum guia avisa sobre ela. Breakpoints de media query escritos em px não respondem ao zoom de tamanho de fonte do navegador da forma que você esperaria.
Imagine um breakpoint em width: 600px em que uma barra lateral se recolhe. Um usuário com visão reduzida define o padrão do navegador como 24px para ler confortavelmente. Seu conteúdo agora precisa de mais espaço horizontal, e o texto maior quer refluir mais cedo. Mas um breakpoint em px não sabe que o texto cresceu; ele ainda dispara exatamente a 600px de viewport, então o layout muda no momento errado e o conteúdo fica apertado ou se sobrepõe.
Compare as duas abordagens:
/* breakpoint em px — ignora a preferência de tamanho de fonte do usuário */
@media (min-width: 600px) {
.sidebar { display: block; }
}
/* breakpoint em em/rem — responde ao tamanho de fonte do usuário */
@media (min-width: 37.5em) {
.sidebar { display: block; }
}
37.5em é 600px no padrão de 16px (600 ÷ 16 = 37.5). A diferença é comportamental: quando o usuário dobra o tamanho de fonte padrão, o breakpoint em em efetivamente dobra também, então o layout muda numa largura de viewport proporcional ao texto, exatamente quando o conteúdo precisa. O breakpoint em px fica congelado.
Uma peculiaridade que vale conhecer: nas condições de media query, em e rem resolvem ambos contra o tamanho de fonte padrão do navegador, e não contra qualquer override do html, então se comportam de forma idêntica ali. Qualquer das duas unidades corrige o bug; px o causa.
A tabela de decisão por propriedade
Quando você estiver em dúvida, esta tabela resolve, sem precisar rederivar a lógica toda vez.
| Propriedade | Unidade recomendada | Por quê |
|---|---|---|
font-size | rem | Escala com a preferência de tamanho de fonte do usuário |
padding / margin | rem | O espaçamento escala junto com o texto |
border | px | Linhas finas devem permanecer nítidas e fixas |
deslocamento de box-shadow | px | Um detalhe preciso de renderização, não conteúdo |
border-radius | rem | Mantém o arredondamento dos cantos proporcional à escala |
| media query | em / rem | Breakpoints devem responder ao zoom de tamanho de fonte |
width / max-width | rem (muitas vezes ch para texto) | Larguras de layout escaláveis; ch limita o comprimento da linha |
line-height | sem unidade | Um multiplicador sem unidade é herdado corretamente |
A linha do line-height merece uma nota porque é um bug comum. Sempre escreva line-height: 1.5, sem unidade. Um valor sem unidade é um multiplicador que cada elemento calcula contra o seu próprio tamanho de fonte, então os elementos aninhados permanecem legíveis. Escreva line-height: 1.5em ou 24px em vez disso e o comprimento computado é herdado, o que significa que um filho com fonte maior mantém a altura de linha do pai e seu texto começa a colidir. Sem unidade evita o problema inteiro.
Convertendo entre px e rem
A aritmética é pequena o bastante para fazer de cabeça assim que você fixa a âncora: 16px = 1rem. Divida por 16 para ir a rem, multiplique por 16 para voltar a px.
| px | rem (base de 16px) |
|---|---|
| 8px | 0.5rem |
| 12px | 0.75rem |
| 16px | 1rem |
| 24px | 1.5rem |
| 32px | 2rem |
Se você usar o truque dos 62.5%, a base vira 10px e a conta fica ainda mais simples: basta dividir ou multiplicar por 10, então 24px = 2.4rem. A única regra é converter sempre contra a base que a sua folha de estilos de fato define.
Para todo o resto, como valores ímpares, uma raiz customizada ou a conversão em lote de uma exportação do Figma, pule a conta mental e use o conversor de px para rem ou o conversor de rem para px. Ambos deixam você definir qualquer tamanho de fonte de raiz e converter nas duas direções em tempo real. E se depois disso você estiver arrumando uma folha de estilos cheia de unidades misturadas, o formatador de CSS normaliza o espaçamento e a indentação para você.
Erros comuns
Alguns padrões causam a maior parte da dor de cabeça relacionada a unidades:
Definir o tamanho de fonte da raiz em px. Escrever html { font-size: 16px } (em vez de deixar o padrão ou usar 100% / uma porcentagem) sobrescreve por completo a preferência de tamanho de fonte do navegador do usuário. Os valores em rem ainda computam contra ele, mas o leitor não consegue mais escalar a página inteira. Deixe a raiz no padrão ou use uma porcentagem.
Misturar px e rem sem sistema. Alguns tamanhos de fonte em px, outros em rem, espaçamento dividido entre os dois: o resultado é um layout que escala de forma irregular quando o usuário ajusta o texto. Escolha rem como padrão e reserve px para as exceções deliberadas da tabela de decisão.
Usar em para espaçamento global. Em em contêineres amplamente aninhados reintroduz a armadilha do composto, então um padding lá no fundo da árvore resulta em algo que ninguém pretendia. Mantenha o espaçamento global em rem; guarde o em para valores locais, com escopo de componente.
Dar uma unidade ao line-height. Como visto acima, line-height: 24px ou 1.5em é herdado como um comprimento computado e quebra em elementos com tamanhos de fonte diferentes. Sempre use um multiplicador sem unidade.
FAQ
rem é melhor que px?
Para a maior parte do dimensionamento, sim: rem é melhor que px porque escala com a preferência de tamanho de fonte do navegador do usuário, que o px ignora. Mas “melhor” depende da propriedade: px é a escolha certa para detalhes fixos como bordas de 1px e deslocamentos de sombra que devem permanecer nítidos. Use rem para dimensionar conteúdo, px para detalhes de renderização.
Quanto é 1rem em pixels?
1rem equivale ao tamanho de fonte da raiz em pixels, que é 16px por padrão em praticamente todos os navegadores. Então 1rem = 16px, 1.5rem = 24px e 2rem = 32px numa configuração comum. Se uma folha de estilos sobrescreve html { font-size }, por exemplo para 10px via truque dos 62.5%, então 1rem equivale a esse valor.
Devo usar rem ou em para font-size?
Use rem para font-size em quase todos os casos. O rem mede contra a raiz, então permanece previsível por mais profundamente que um elemento esteja aninhado. O em mede contra o tamanho de fonte do pai, que compõe árvore abaixo e faz o texto aninhado inchar de forma inesperada. Reserve em para valores locais ligados a um único componente.
Quando devo usar px em vez de rem?
Use px para valores que não devem escalar com o tamanho de fonte do usuário: bordas de 1px, deslocamentos precisos de box-shadow, contornos de anel de foco e outros detalhes fixos de renderização. Esses são detalhes nítidos de design, e não conteúdo, então fixá-los em px é a escolha mais acessível. Tudo relacionado a conteúdo ainda deve usar rem.
Por que as media queries quebram quando uso px?
Breakpoints de media query em px não respondem ao zoom de tamanho de fonte do navegador. Quando um usuário aumenta a fonte padrão, seu conteúdo precisa de mais espaço, mas um breakpoint em px ainda dispara na mesma largura de viewport, então o layout muda no momento errado. Use breakpoints em em ou rem, que escalam com o tamanho de fonte do usuário.
O que é o truque de font-size dos 62.5%?
O truque dos 62.5% define html { font-size: 62.5% }, deixando o tamanho de fonte da raiz em 10px (62.5% de 16). Com uma base de 10px, a conta de rem vira “dividir por 10”: 24px = 2.4rem, 12px = 1.2rem. Os desenvolvedores então definem body { font-size: 1.6rem } para restaurar o texto do corpo legível em 16px.
Tudo bem misturar px, rem e em?
Sim, misturar px, rem e em é correto quando cada um segue a propriedade que lhe convém: rem para tipografia e espaçamento, px para detalhes fixos, em para valores locais com escopo de componente. O que causa problema é misturá-los sem sistema, como alguns tamanhos de fonte em px e outros em rem. Escolha rem como padrão e trate px e em como exceções deliberadas.
Que unidade devo usar para padding e margin?
Use rem para padding e margin, assim o espaçamento escala junto com o texto quando o usuário ajusta a fonte. Isso mantém o layout proporcional e acessível. Reserve em para padding que deve acompanhar o tamanho de fonte do próprio elemento, como um botão cujo padding cresce junto com o texto, e evite em em contêineres profundamente aninhados, onde ele compõe.