Camilo Micheletto
Posted on August 17, 2021
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.
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 deline-height
base, mesma coisa com ofont-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;
}
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.
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
}
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>
O valor do font-size
na div
for 22px e o line-height
for 1em
.text-container {
font-size: 22px;
}
.text {
line-height: 1em;
}
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);
}
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
O site da W3 (Não confundir com W3Schools)
Sim, eu li esse calhamaço, mas não é tão ruim não tá? Recomendo demais.Episódio do The CSS Podcast sobre unidades CSS
Nunca achei que eu ia aprender tanto com um podcast sobre CSS, o Adam e a Una são dois nerds, provavelmente vou revisar esse texto quando escutar novamente.
*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 😙
Posted on August 17, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.