Design

px vs rem vs em: qual usar e o que cada uma quebra

As três resultam no mesmo tipo de comprimento. A diferença está em quem controla o número que multiplica cada uma.

Use rem para tamanhos de fonte, espaçamentos e media queries. Use px para o que não pode mudar de tamanho: uma borda de um pixel, um ícone fixo, uma linha divisória fina. Use em quando um valor deve acompanhar o tamanho de fonte do elemento em que ele está, como o padding dentro de um botão. As três terminam como a mesma coisa, um comprimento em pixels CSS; a única diferença é por qual número elas são multiplicadas e quem controla esse número.

UnidadeMultiplicada porControlada por
pxNada. 1px é 1px.Você, e mais ninguém.
remO tamanho de fonte computado do elemento html.A configuração do navegador do leitor — a não ser que você a sobrescreva.
emO tamanho de fonte computado do próprio elemento. Na propriedade font-size, o do pai.O lugar onde o elemento estiver na cascata.

Um pixel CSS é um pixel de verdade?

Não. O CSS fixa uma polegada em exatamente 96 px, o que amarra cada unidade absoluta a todas as outras: 1pt é exatamente quatro terços de pixel e 1cm é 96 dividido por 2,54, cerca de 37,8 px. Essas proporções valem em qualquer dispositivo. O que elas não descrevem é nada físico. Uma tela com o dobro da densidade de pixels pinta cada pixel CSS com quatro pixels de hardware, e um celular aplica mais uma escala por cima para que o texto continue legível à distância do braço. px é estável em relação ao resto do seu layout e não significa nada em relação ao vidro.

Por que rem é o padrão para texto

Porque 16 px não é uma constante, é um padrão, e padrões são alterados. Chrome, Firefox e Edge colocam um controle de tamanho de texto no painel de configurações comum, sem precisar de nenhum menu de acessibilidade. Coloque 20 e cada rem da página cresce um quarto: 1rem deixa de significar 16 px e passa a significar 20. Tudo o que você dimensionou em px nessa mesma página não se mexe.

Esse é o argumento inteiro, e vale ser honesto sobre o tamanho dele. A afirmação comum de que texto em px é inacessível é exagerada. O próprio documento Understanding do W3C para o critério de sucesso 1.4.4 — o que exige que o texto sobreviva a um redimensionamento de 200% sem quebrar — considera o conteúdo aprovado se qualquer mecanismo de escala de texto oferecido pelo navegador der conta, e o zoom de página inteira amplia px junto com todo o resto. Por essa leitura, texto corrido em px não reprova nessa caixinha.

O que ele reprova é o leitor que nunca toca no zoom. O zoom também amplia imagens, layout e comprimento de linha, e muita gente só quer palavras maiores. Essas pessoas ajustaram o tamanho de texto do navegador uma vez, anos atrás, e depois caem numa página cujo texto corrido é font-size: 14px e nada acontece. A opção “Aplicar zoom apenas no texto” do Firefox é esse mesmo grupo de pessoas pedindo a mesma coisa. rem responde a elas, e não custa nada para você.

Quando px ainda é a resposta certa

Dimensionar tudo em rem é um erro de verdade, só que menos comum. Use px onde escalar deixaria o valor errado, e não apenas diferente:

Misturar unidades dentro de uma mesma regra é normal, não é code smell. padding: 1rem; border-bottom: 1px solid está exatamente certo: o espaço acompanha o texto, a linha não.

Para que serve o em de verdade

em se refere ao tamanho de fonte do próprio elemento — com uma exceção que causa quase toda a confusão. Na propriedade font-size, em se resolve contra o tamanho de fonte do pai, porque o tamanho do próprio elemento é justamente o que está sendo calculado. Em todo o resto, padding incluído, ele se resolve contra o tamanho já computado do próprio elemento.

Essa exceção é o motivo de uma lista aninhada estilizada com 0.9em encolher a cada nível: 0,9, depois 0,81, depois 0,729, e quatro níveis abaixo uma base de 16 px virou cerca de 10,5 px. É também o que torna o em genuinamente útil. Defina um único tamanho de fonte em um botão, escreva o padding, o gap e o border radius dele usando em, e o componente inteiro escala como uma unidade a partir de um número só. Mude esse número e o botão cresce corretamente sem tocar em outras quatro declarações.

A regra prática: em quando o valor pertence ao componente, rem quando pertence à página. O padding de um botão é assunto do componente. O espaço entre duas seções é assunto da página.

Em media queries, em e rem são a mesma coisa

A especificação é explícita: unidades relativas dentro de uma media query se resolvem contra o tamanho de fonte inicial, nunca contra o resultado de uma declaração. Então @media (min-width: 40em) e @media (min-width: 40rem) produzem um breakpoint idêntico, e nenhum dos dois é afetado por html { font-size: 62.5% }. Os dois continuam seguindo o tamanho de texto padrão do leitor, que é exatamente o ponto: quem lê a 20 px chega ao layout mais largo depois, quando o texto maior realmente precisa do espaço. Um breakpoint em px ignora isso por completo.

Por quanto você divide para chegar a rem?

Pelo tamanho de fonte da raiz. No padrão de 16, isso dá 24 px = 1.5rem, 12 px = 0.75rem, 14 px = 0.875rem, 18 px = 1.125rem. Os redondos você decora em uma semana. Os quebrados você consulta para sempre.

Fazer isso em uma folha de estilos inteira é onde a tarde vai embora, então vale a pena manter um conversor de px para rem aberto ao lado do editor. O botão “Ler desta janela” preenche o tamanho de fonte raiz que o seu navegador realmente computou, que é o jeito mais rápido de descobrir que algo no seu próprio CSS já sobrescreveu esse valor.

O truque do 62.5% vale a pena?

html { font-size: 62.5% } faz 1rem valer 10 px para um leitor no padrão, então 1.6rem pode ser lido direto na página como “16px” e a divisão desaparece. A raiz continua sendo uma porcentagem da configuração do leitor, então a preferência dele sobrevive e isso não é uma falha de acessibilidade. A conta chega pela herança. Agora todo elemento sem estilo parte de 10 px, então o body precisa de um reset imediato, e qualquer coisa que você jogue ali dentro escrita em rem — um date picker, uma biblioteca de componentes, um widget incorporado — é renderizada 37,5% menor do que o autor pretendia. Tudo bem em uma base de código que você controla de ponta a ponta. Nada bem dentro do design system de outra pessoa.

Os quatro erros que vale a pena conhecer

Definir html { font-size: 16px }. Esse é o que cancela silenciosamente tudo o que veio antes. Ele substitui a preferência do leitor pelo seu número, e agora a sua folha de estilos cuidadosamente baseada em rem se comporta exatamente como uma baseada em px. Se você precisa ajustar a raiz, use uma porcentagem ou deixe ela em paz.

Colocar uma unidade no line-height. Um line-height: 1.5 sem unidade é herdado como proporção, então cada filho o recalcula a partir do próprio tamanho de fonte. line-height: 1.5rem é herdado como um comprimento fixo, e um título que o herda recebe 24 px de caixa de linha em volta de um texto de 32 px. Sem unidade, sempre.

Usar em para espaçamento no nível da página. A margem entre duas seções não deveria mudar porque uma delas por acaso contém texto menor. Esse é um valor em rem.

Confiar em uma conversão de em ou % que você não conferiu. px, rem, pt e as unidades físicas são aritmética exata. em e % não são: o valor real deles depende do tamanho de fonte computado de um elemento que você precisa ir procurar, e nenhum conversor consegue ler a sua cascata por você. Digite o tamanho errado do pai e sai uma resposta errada com toda a cara de certa.

Então, o que fazer na prática

Deixe o tamanho de fonte da raiz em paz. Escreva tamanhos de fonte, espaçamento vertical e breakpoints em rem. Escreva bordas, linhas finas e gráficos de tamanho fixo em px. Recorra ao em dentro de um componente quando quiser que um único tamanho de fonte comande todo o resto, e em nenhum outro lugar. Mantenha o line-height sem unidade.

Isso cobre quase tudo. As unidades restantes são mais estreitas: pt, cm e mm só significam algo em uma folha de estilos de impressão; % significa uma coisa diferente em quase toda propriedade em que aparece; ch e ex dependem das métricas do arquivo de fonte específico, que é o motivo de nenhum conversor conseguir calculá-las para você. E se uma página está escrita em rem e ainda assim é difícil de ler, as unidades nunca foram o problema: a razão de contraste que o seu texto exige é a outra metade da legibilidade, e é a metade que as pessoas pulam.

A aritmética é trivial; fazer isso quarenta vezes não é. É por isso que vale a pena manter o conversor de unidades CSS aberto em uma aba. Ele mostra um valor em onze unidades ao mesmo tempo, e cada linha diz qual das suas quatro suposições — tamanho de fonte da raiz, tamanho de fonte do elemento, largura da viewport, altura da viewport — produziu aquele número. As linhas de em e % só são tão confiáveis quanto o tamanho de fonte que você digitou, e ch e ex estão ausentes de propósito, porque métricas de glifo não podem ser deduzidas por aritmética.

Se você está arrumando as unidades de uma folha de estilos, os valores de cor costumam ser a próxima coisa que aparece. HEX, RGB e HSL comparados faz a mesma pergunta que este post — qual notação dá para editar à mão de verdade — só que sobre cor em vez de comprimento.

Perguntas frequentes

Devo usar px ou rem no CSS?

Use rem para tudo o que deve acompanhar o tamanho de texto do leitor: tamanhos de fonte, espaçamento vertical e breakpoints. Use px para tudo o que ficaria errado, e não apenas diferente, em um tamanho maior, como uma borda fina, um ícone de resolução fixa ou um deslocamento pequeno de sombra. Os dois convivem na mesma regra com frequência: padding em rem com uma borda de 1px embaixo está certo, não é code smell.

Qual é a diferença entre em e rem?

rem é medido contra o tamanho de fonte do elemento raiz html, então um rem é o mesmo comprimento em toda a página. em é medido contra o tamanho de fonte do elemento em que aparece, exceto na própria propriedade font-size, onde usa o do pai, porque o tamanho do próprio elemento é o que está sendo calculado. Essa exceção é o motivo de em se acumular através de elementos aninhados e rem nunca se acumular.

É ruim usar px para tamanho de fonte?

Não reprova no critério de sucesso 1.4.4 da WCAG, que é atendido se qualquer mecanismo de escala de texto oferecido pelo navegador funcionar, e o zoom de página inteira amplia texto em px junto com o resto da página. O que px ignora é o leitor que aumentou o tamanho de texto padrão do navegador em vez de usar o zoom; essa pessoa não ganha nada com a sua página. Como rem não custa nada a mais, há pouca razão para definir texto corrido em px.

html { font-size: 62.5% } causa problemas de acessibilidade?

Por si só, não. A raiz continua sendo uma porcentagem do tamanho de texto que o leitor escolheu, então a preferência dele ainda escala a página inteira. O custo real é a herança: agora todo elemento parte de 10px em vez de 16, então o body precisa de um reset explícito, e qualquer CSS de terceiros escrito em rem é renderizado 37,5% menor do que o pretendido.

Breakpoints devem ser em px, em ou rem?

em e rem se comportam de forma idêntica em media queries: a especificação do CSS diz que ali as unidades relativas se resolvem contra o tamanho de fonte inicial e ignoram qualquer font-size definido no elemento html. Qualquer uma das duas faz os breakpoints seguirem a preferência de tamanho de texto do leitor, então quem lê com texto maior chega ao layout mais largo quando o texto realmente precisa do espaço. Um breakpoint em px ignora essa preferência por completo.

Por que minha lista aninhada fica cada vez menor?

Porque um font-size em em multiplica contra o tamanho de fonte do pai, então ele se acumula uma vez por nível de aninhamento. Uma regra de 0.9em é 0,81 do original dois níveis abaixo e 0,729 três níveis abaixo; partindo de 16px, isso dá cerca de 11,7px. Escreva essa regra em rem, ou limite o alcance dela com um seletor de filho direto para que valha só no primeiro nível.

Última atualização 19 de setembro de 2026