DEV Community

Cover image for Entendendo unidades CSS e quando utilizá-las
Camilo Micheletto
Camilo Micheletto

Posted on • Updated on

Entendendo unidades CSS e quando utilizá-las

Nesse artigo vou explicar sobre as unidades CSS px, %, em, rem, ch, e ex e exemplos de casos de uso delas. Esse artigo será escrito em duas partes, detalhes do que vou abordar na segunda no final do texto.


Introdução

TLDR, porque eu escrevi esse artigo e o que eu decidi omitir dele.

No Twitter e nos grupos do Telegram que eu participo vejo com muita frequência dúvidas sobre como e onde usar certas unidades CSS ou pessoas utilizando e manipulando unidades de forma incorreta. Para deixar claro, o que considero como uso incorreto de unidades CSS é utilizá-las de maneira que prejudique a acessibilidade e realizar operações com elas que o browser não consegue computar ou que são baseadas em números mágicos ou lógicas obscuras. Penso que o motivo dessas dúvidas é que geralmente as explicações sobre essas unidades vem desacopladas da explicação de como elas são aplicadas no dia-a-dia e, os casos de uso que a gente realmente entende como usar elas no seu potencial máximo vão ocorrendo com tempo e experiência. Abaixo vou explicar um pouco sobre cada unidade de medida e colocar como exemplo (quando possível) como e porque utilizei cada uma delas.

Por motivos de brevidade e utilidade omiti unidades com escopo muito específico (como Q, Hz) e unidades novas em fase experimental (Unidades do módulo CSS nível 4, lh, rlh, cap, etc).


Unidades absolutas e relativas

Nas sessões abaixo vocês vão cansar de ler sobre unidades absolutas e relativas. Unidades relativas são unidades cujo valor depende de um fator externo, como por exemplo a % que depende do valor do elemento pai, do vh que varia de acordo com a altura do viewport, e assim por diante. Unidades absolutas são unidades ancoradas em medidas físicas reais, é o caso do px (píxeis) e do cm (centímetros).


px

Um píxel é o conjunto de três pontos minúsculos - um vermelho, uma verde e um azul (RGB) - que juntos compõe tudo aquilo que você enxerga na tela que você está lendo esse post. Cada cor desse píxel exibe de 0 a 255 gamas de cores, somando um pouco mais que 16 milhões de possibilidades de cor. Por causa da ~bobagem~ moda do pixel-perfect, muitas pessoas se sentiam inclinadas a declarar todas as medidas de todos elementos com os mesmos pixeis utilizados no layout.
Com o surgimento de diversos tamanhos de dispositivos, cada um com diferentes formatos e taxas de densidade de pixel por polegada, ficou muito difícil manter esse valor absoluto pra elementos que precisam se adaptar de acordo a tela.

Quando usar?
Generalizando - use pra elementos e medidas que não irão mudar, independente do contexto ou tamanho de viewport (tela do dispositivo). Um bom exemplo de uso são bordas e alguns box-shadows e pra definir valores mínimos e máximos de elementos.

Geralmente defino um tamanho mínimo e máximo para botões pra manter uma superfície clicável grande em dispositivos pequenos mesmo que o texto seja pequeno e para restringir o tamanho do botão dentro de elementos de bloco, pois se deixar ele fica gigante, da largura do elemento pai.

Botão ocupando toda largura do container sem ter max-width
Max width restringindo o tamanho total do botão

A preocupação de se um elemento tem a largura ideal para ser clicado pelos dedos é um tema real de UX chamado finger-friendly design, esse artigo da Smashing Magazine explica muito bem o conceito.

Quando não usar?
Bom, seria muito fácil assumir que tudo que não se encaixa nos requisitos de "Quando não usar?" entraria aqui, mas quero ressaltar que jamais se deve definir um tamanho de fonte em píxel.
Vamos supor que você coloque a font-size do elemento <p> em 16px. Em um dispositivo retina (as telas da apple por exemplo), existem 4 vezes mais pixeis dentro da mesma polegada do que em telas comuns, mas apesar da diferença de contexto, seu valor continuará estático. Caso pessoas com deficiências visuais apliquem zoom na sua página, os textos declarados com px não aumentarão com o zoom, causando um problema f*dido de acessibilidade.

O que a WCAG (Diretrizes de Acessibilidade para o Conteúdo da Web) diz sobre zoom e font-size?

  • WCAG 1.4.4: Os usuários devem ser capazes de redimensionar textos sem tecnologia assistiva em até 200 por cento, sem perda de conteúdo ou funcionalidade. (Nível AA).
  • WCAG 1.4.10: Os usuários devem ser capazes de redimensionar o texto sem serem forçados a usar a barra de rolagem horizontal e verticalmente para ler o conteúdo. (Nível AA).

Isso é de suma importância pois usuários com baixa acurácia visual simplesmente não vão conseguir consumir seu conteúdo, é ruim pra você e especialmente ruim pra essas pessoas.

Você pode ler mais sobre como solucionar esse problema com zoom nesse post incrível do Adrian Roselli.


%

Porcentagens são quase sempre relativas às medidas do elemento pai delas. Se você declarar uma width de 20% em um elemento, a largura desse será 20% da largura do pai, mesma coisa com outras propriedades como height e margin / padding. Agora vem a parte do quase:

  • Um line-height de 150% é o 1.5x maior que o valor de line-height base, mesma coisa com o font-size. Com base eu me refiro valores padrão de cada propriedade CSS, essas propriedades possuem um valor inicial próprio, definido pelo browser (user agent) ou pré-definidos pelo usuário (root).

  • Um transform: translateX(-100%); significa que o elemento irá se movimentar para esquerda uma quantia relativa ao seu próprio tamanho, então se o elemento tiver 15px, ele se movimentará 15px para a esquerda.

Quando usar?
O melhor caso de uso que eu posso imaginar é a largura e altura de elementos aninhados, ou seja, que o pai não seja o <body>. Isso porque quase todos elementos que estão dentro de um pai não podem ter largura ou altura maiores que a do pai, facilitando muito na criação de elementos responsivos. Se você tem a certeza que os elementos diretamente no body não vão extrapolar o tamanho do viewport (a não ser que seu layout seja horizontal e não vertical), se todos elementos internos desse são uma porcentagem do tamanho do pai, esses dificilmente vão estourar o tamanho do container.

Um exemplo que gosto muito é usar porcentagem com CSS grid. O ideal é sempre usar a unidade fr (vou falar dela mais adiante), porém nesse caso em específico ele é muito poderoso.

Caso: Vamos supor que temos um layout que todo conteúdo fica no meio do site, como acontece em redes sociais como o Tumblr, porém no celular o espaço das laterais tem que diminuir expressivamente pro conteúdo caber. Esse layout é conhecido como holy grail layout, por ser um padrão amplamente adotado na web ainda hoje.

A maioria das pessoas logo pensa em colocar padding e media queries ou margin: 0 auto, mas tem essa solução com grid que é bem elegante:

.container {
  display: grid;
  grid-template-columns: 1fr min(100%, 600px) 1fr;
}

.conteudo {
  grid-column: 2;
}
Enter fullscreen mode Exit fullscreen mode

A função min() vai selecionar entre 600% e 100% qual o menor valor que ela irá retornar, em telas grandes a coluna do meio terá no máximo 600px e em telas menores que isso ela terá 100% da largura. Como a unidade fr calcula o espaço disponível, como 100% ocupa todo o espaço horizontal, as laterais serão iguais a zero.

Exemplo do uso da função min deixando a largura da coluna central do grid em 100% em dispositivos menores

Você pode ler mais sobre essa estratégia nesse post maravilhoso do Josh Comeau.

Quando não usar?
Evite usar com parâmetros relacionados a fonte e tome sempre o cuidado de declarar um valor máximo e mínimo para componentes que são elementos e não containers, um botão com uma width de 20% pode ficar ridiculamente maior em telas grandes.

Outra coisa que não faz mais sentido fazer é declarar font-size: 100%; no elemento body, html ou :root. Isso era feito pois como a porcentagem nesse caso diz respeito às definições de usuário, isso garantiria a flexibilidade da fonte. Porém o rem já faz isso direto da caixa.


rem

O rem é o root font-size, ou seja, 1rem é igual ao tamanho total do font-size do elemento raiz e, na ausência desse, o tamanho inicial da propriedade font-size. Ambos valores serão 16px a não ser que o usuário personalize o tamanho da fonte do sistema ou utilize zoom.

O rem corresponde a uma fração desse valor, então 1.5rem equivalem a 24px, visto que:

16px * 1.5 = 24px

Quando usar?
Para o tamanho de fontes, raramente há um caso de uso que algo que não seja tamanho de fonte precise se pautar em rem, visto que por mais que essa medida seja relativa, seu valor muda apenas em casos muito específicos.

Quando não usar?
Não consigo pensar em nenhuma contra indicação de uso, mas da maneira de utilizar. Evitem de toda a forma converter rem em px, caso seu design system utilize uma escala modular onde todo font-size é maior que o próximo de acordo com uma proporção, crie uma variável base e use a função calc(), você criar listas com números quebrados gigante é difícil de manter, entender e justificar.
Para mais informações sobre esse caso, esse é um ótimo artigo sobre modular scale com CSS.

Outra contraindicação é o "hack" de definir o font-size no elemento :root para "facilitar" a conversão de px pra rem:

:root {
  font-size: 10px;
}

.container {
  font-size: 1.5rem; // equivalente a 15px
}
Enter fullscreen mode Exit fullscreen mode

Isso é extremamente prejudicial pra acessibilidade e cai no problema do zoom que eu citei lá na sessão sobre px.


em

O em funciona quase da mesma forma que o rem, porém ao invés de ser igual ao font-size definido no :root ela é igual ao font-size do elemento em que ela for utilizado.

Se tivermos um p dentro de uma div

<div class="text-container">
  <p class="text"> Lorem ipsum dorsit amet</p>
<div>
Enter fullscreen mode Exit fullscreen mode

O valor do font-size na div for 22px e o line-height for 1em

.text-container {
  font-size: 22px;
}

.text {
  line-height: 1em;
}
Enter fullscreen mode Exit fullscreen mode

O 1em vai ser 100% do font-size do container do elemento pois, se não declarado, o elemento p vai herdar o font-size de .text-container. Caso tanto o font-size quanto o line-height estiverem na classe .text, você vai obter o mesmo resultado.

Quando usar?
Como a gente sempre precisa ficar atento às fontes declaradas nos elementos pai pra ter controle sobre como o em escala, eu geralmente uso essa unidade pra ícones e elementos que precisam escalar junto com o texto, como botões e inputs.

No exemplo abaixo eu criei um botão que aumenta e diminui o padding de acordo com o font-size, o padding está declarado em em.

Quando não usar?
Não usar em elementos que estão em contextos muito aninhados de font-size pois ficará difícil mapear qual font-size o em determinado elemento está se baseando. Todas as afirmações sobre rem se aplicam também.


ch e ex

Coloquei as duas unidades juntas pois elas funcionam de maneira parecida - ambas são baseadas em medidas dos caracteres da primeira font-family disponível.

O ch é referente a largura do '0' (zero) da fonte, já o ex é referente a altura do caractere 'x' minúsculo.

Quando usar?
Como 1ch diz respeito a mais ou menos um caractere (o valor é bem aproximado e varia dependendo da fonte), é bem interessante pra width de campos de texto. Estudos indicam que uma linha de texto que tem entre 50 e 60 caracteres de largura apresenta uma legibilidade melhor do que linhas mais curtas ou mais largas.

Essa regra combina muito com a função clamp()

p {
  width: clamp(50ch, 100%, 60ch);
}
Enter fullscreen mode Exit fullscreen mode

Eu particularmente gosto de usar pra propriedade gap quando uso textos dentro de um elemento flex ou grid, pois como ela escala menos que o rem (A cada 1 rem são 16px), você consegue fazer espaçamentos de texto menores sem escrever números muito quebrados.

Quando não usar?
Não consegui pensar em nenhuma contraindicação, tem muitos casos de uso que outras unidades funcionam melhor, mas nunca tive problema em utilizar ela em outros contextos não ligados a texto, se você já teve, comente, vai ser maneiro.


Como isso aqui já está virando um livro, resolvi quebrar em duas publicações, na próxima vou falar de:

  • Números inteiros
  • Unidades de viewport
  • Unidades de ângulo
  • Unidades de resolução
  • Unidades para impressos

Fontes e leituras adicionais

*Observação: *
Se nesse texto eu:

  • Falei merda
  • Caguei regra
  • Perdi a oportunidade de usar de linguagem neutra
  • Cometi erros de português
  • Poderia ter explicado algo melhor ou falei algo que não fez sentido

Ou se só ficou alguma dúvida mesmo.
Pode comentar aqui ou me chamar no Twitter que eu vou amar ok?

Obrigadíssimo 😙

Discussion (3)

Collapse
santosdanilo profile image
Danilo Santos

Muito bom o texto, já me debati bastante sobre essa questão de unidade de medida, que geralemente não tem um guia tão direto, e com as razões.

Collapse
lixeletto profile image
Camilo Micheletto Author

Eu fiquei meio preocupado de colocar a minha opinião de como usar e não usar mas acho que talvez seja esse tipo de coisa que faça com que as pessoas discutam mais sobre isso e a gente veja mais gente publicando sobre sua maneira e casos de uso de unidades. É uma dúvida tão comum e tão subestimada, o debate é muito importante!

Collapse
angelicacamp profile image
Angélica Campos

Olá Camilo, muito bom o texto! Eu estou iniciando e tenho muitas dúvidas referente as unidades do CSS. Obrigada por compartilhar :)