Capa do Ebook gratuito Arquitetura de CSS Escalável: BEM, ITCSS e Design Tokens para Projetos Reais

Arquitetura de CSS Escalável: BEM, ITCSS e Design Tokens para Projetos Reais

Novo curso

22 páginas

Utilitários com propósito: quando usar, como nomear e como evitar duplicação

Capítulo 16

Tempo estimado de leitura: 13 minutos

+ Exercício

O que são utilitários “com propósito”

Utilitários são classes pequenas e diretas, criadas para aplicar uma única responsabilidade visual (ou um conjunto muito pequeno e coerente) sem depender do contexto do componente. A ideia de “utilitários com propósito” é evitar dois extremos comuns: (1) utilitários genéricos demais, que viram um dial infinito de combinações e tornam o HTML ilegível; (2) ausência total de utilitários, que força repetição de CSS em vários componentes para ajustes recorrentes.

“Com propósito” significa que cada utilitário existe porque resolve um problema recorrente e mensurável no projeto, com regras claras de uso, nomeação e limites. Em vez de criar classes para qualquer valor arbitrário (ex.: .mt-13), você cria utilitários alinhados a decisões do design (tokens) e a padrões de layout/ajuste que aparecem repetidamente (ex.: .u-mt-sm ou .u-stack-md).

O que utilitários não são

  • Não são “atalhos” para burlar a arquitetura do CSS quando um componente está mal modelado.
  • Não são substitutos de componentes: um botão não deveria ser montado com 12 utilitários se existe um componente de botão.
  • Não são uma coleção infinita de valores: utilitários devem ser limitados por escala (tokens) e por um conjunto de propriedades permitido.

Quando usar utilitários (e quando não usar)

Use utilitários quando

  • O ajuste é transversal: o mesmo tipo de ajuste aparece em muitos componentes e páginas (ex.: espaçamento entre seções, alinhamento pontual, visibilidade responsiva).
  • O ajuste é “de composição”: você está compondo blocos existentes e precisa de pequenas regras de encaixe (ex.: adicionar gap em um wrapper, centralizar um item, aplicar max-width em um container).
  • Você quer reduzir CSS específico para casos pontuais sem criar novos modificadores em cada componente (ex.: um card que, em uma página específica, precisa de margin-top extra).
  • O valor vem de uma escala (tokens): espaçamentos, tamanhos, raios, sombras, z-index, etc., com opções discretas.
  • O comportamento é previsível e seguro: utilitários devem minimizar efeitos colaterais e não depender de estrutura interna do componente.

Evite utilitários quando

  • O estilo faz parte do contrato do componente: se todo Button precisa de padding e cor, isso é do componente, não do utilitário.
  • O ajuste é específico e raro: se só aparece uma vez, pode ser melhor resolver no CSS do contexto (ou revisar a necessidade).
  • Você está corrigindo um bug estrutural: por exemplo, usar utilitário para “consertar” um layout quebrado por falta de um wrapper adequado.
  • Você precisa de seletores complexos: utilitários devem ser simples; se exige :nth-child, encadeamento ou dependência de DOM, isso não é utilitário.
  • O utilitário vira uma API paralela: se a equipe começa a “programar CSS” no HTML com dezenas de classes por elemento, você perde legibilidade e governança.

Tipos de utilitários com propósito (catálogo recomendado)

Um catálogo enxuto ajuda a equipe a reconhecer padrões e evita a explosão de classes. Abaixo, categorias comuns e seguras.

1) Espaçamento (margin/padding) baseado em escala

Utilitários de espaçamento são úteis porque aparecem em composição de páginas e ajustes de densidade. O propósito aqui é: “aplicar espaçamentos previstos pela escala do design”.

/* Exemplo de escala (tokens) já definida no projeto) */
:root {
  --space-0: 0;
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-6: 1.5rem;
  --space-8: 2rem;
}

/* Utilitários com propósito */
.u-mt-0 { margin-top: var(--space-0); }
.u-mt-4 { margin-top: var(--space-4); }
.u-mb-6 { margin-bottom: var(--space-6); }
.u-p-4  { padding: var(--space-4); }
.u-px-4 { padding-left: var(--space-4); padding-right: var(--space-4); }
.u-py-6 { padding-top: var(--space-6); padding-bottom: var(--space-6); }

Repare que os valores não são arbitrários: são chaves da escala. Isso reduz duplicação e impede “microvariações” que viram dívida técnica.

Continue em nosso aplicativo

Você poderá ouvir o audiobook com a tela desligada, ganhar gratuitamente o certificado deste curso e ainda ter acesso a outros 5.000 cursos online gratuitos.

ou continue lendo abaixo...
Download App

Baixar o aplicativo

2) Layout de composição (flex/grid) com escopo limitado

Utilitários de layout devem ser poucos e focados em padrões recorrentes. Evite criar uma classe para cada propriedade de flex/grid; prefira utilitários que representem intenções claras.

.u-flex { display: flex; }
.u-inline-flex { display: inline-flex; }
.u-items-center { align-items: center; }
.u-justify-between { justify-content: space-between; }
.u-gap-4 { gap: var(--space-4); }
.u-wrap { flex-wrap: wrap; }

Se você perceber que está combinando sempre .u-flex + .u-items-center + .u-gap-4 em vários lugares, isso é um sinal para criar um utilitário mais intencional (ou um objeto de layout), por exemplo .u-row com variações de gap. O objetivo é reduzir repetição de combinações.

3) Tipografia utilitária (com cuidado)

Tipografia é uma área onde utilitários podem virar “estilização por montagem” rapidamente. Use apenas para ajustes transversais e previsíveis, como alinhamento, peso e truncamento.

.u-text-left { text-align: left; }
.u-text-center { text-align: center; }
.u-text-right { text-align: right; }

.u-font-regular { font-weight: 400; }
.u-font-medium { font-weight: 500; }
.u-font-bold { font-weight: 700; }

.u-truncate {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

Evite utilitários para “tamanho de fonte arbitrário” se isso já é resolvido por estilos de conteúdo ou padrões do sistema. Se existir uma escala tipográfica, use chaves da escala e mantenha poucas opções.

4) Visibilidade e acessibilidade (responsivo e estados)

Utilitários de visibilidade são úteis para composição e adaptação responsiva. O propósito é controlar presença/visibilidade sem criar variações em cada componente.

.u-hidden { display: none !important; }

@media (min-width: 48rem) {
  .u-hidden\@md { display: none !important; }
  .u-block\@md { display: block !important; }
}

Use !important com parcimônia, mas em utilitários de visibilidade ele pode ser justificável para garantir previsibilidade. A regra é: se o utilitário existe para “forçar” um comportamento transversal, ele precisa vencer estilos locais. Ainda assim, limite o conjunto de utilitários com !important e documente-os.

5) “Helpers” de comportamento visual seguro

Alguns utilitários resolvem problemas recorrentes sem interferir no design do componente: limpar floats (se existirem), impedir seleção, controlar overflow, etc. Mantenha-os poucos e bem justificados.

.u-overflow-hidden { overflow: hidden; }
.u-no-select { user-select: none; }
.u-sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

Como nomear utilitários: regras práticas e consistentes

A nomeação precisa ser rápida de escrever, fácil de ler e difícil de usar errado. Um bom padrão de utilitários funciona como uma pequena “API” visual.

Prefixo dedicado

Use um prefixo fixo para utilitários, por exemplo u-. Isso facilita:

  • identificar no HTML o que é utilitário vs. componente;
  • buscar no código;
  • aplicar regras de lint e revisão.

Formato recomendado

Um formato simples e escalável:

  • u-{propriedade}-{valor} para propriedades diretas (ex.: u-mt-4, u-gap-2).
  • u-{intencao} para padrões compostos (ex.: u-truncate, u-sr-only).
  • u-{nome}\@{breakpoint} para responsivo (ex.: u-hidden@md), escapando o @ no CSS quando necessário.

Abreviações: poucas e padronizadas

Abreviações ajudam a reduzir ruído no HTML, mas só funcionam se forem consistentes. Defina um conjunto pequeno:

  • m = margin, p = padding
  • t, r, b, l = top/right/bottom/left
  • x, y = eixos horizontal/vertical

Exemplos: u-mt-4, u-mx-2, u-py-6.

Valores: use chaves, não números “livres”

Mesmo quando o valor parece numérico, ele deve corresponder a uma chave da escala. Se a escala é 0,1,2,3,4,6,8, não crie u-mt-5. Isso força consistência e reduz duplicação por microdiferenças.

Não encode regras de componente no utilitário

Evite nomes como u-card-padding ou u-button-gap. Se o utilitário menciona um componente, ele já não é transversal. Prefira utilitários neutros (u-p-4) ou transforme isso em uma variação do próprio componente.

Como evitar duplicação: governança e critérios de criação

Duplicação em utilitários acontece de três formas: (1) múltiplas classes que fazem a mesma coisa; (2) múltiplas classes que fazem quase a mesma coisa com valores diferentes; (3) múltiplas combinações repetidas no HTML. A seguir, um conjunto de práticas para evitar isso.

1) Tenha uma lista “oficial” de utilitários

Mantenha um arquivo único (ou pasta) de utilitários e trate-o como API pública. A regra de equipe: “se não está no catálogo, não existe”. Isso evita que cada pessoa crie seus próprios utilitários ad hoc.

2) Critério de criação: regra do “3 usos”

Antes de criar um utilitário novo, valide:

  • Já existe algo equivalente?
  • Isso apareceu pelo menos 3 vezes em contextos diferentes?
  • O valor está na escala (tokens)?
  • O utilitário não depende de estrutura interna?

Se a resposta for “não” para qualquer item, provavelmente não é um utilitário; pode ser um ajuste local ou um refinamento do componente.

3) Evite utilitários redundantes por sinônimos

Escolha um vocabulário e mantenha. Exemplo de redundância comum:

  • .u-text-center vs .u-center-text
  • .u-mt-4 vs .u-margin-top-4

Defina um padrão (abreviado ou por extenso) e não aceite variações.

4) Controle de valores: escalas discretas e “tokens only”

Para evitar u-gap-10, u-gap-12, u-gap-14, limite a escala e force o uso de tokens. Se surgir necessidade real fora da escala, o ajuste correto é discutir a escala (token), não criar um utilitário “fora do sistema”.

5) Detecte combinações repetidas e promova para um utilitário composto

Às vezes a duplicação não está no CSS, mas no HTML: a mesma sequência de utilitários aparece em muitos lugares. Exemplo:

<div class="u-flex u-items-center u-justify-between u-gap-4">...</div>
<header class="u-flex u-items-center u-justify-between u-gap-4">...</header>

Se isso se repete, você pode criar um utilitário composto com intenção clara:

.u-row-between {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
}

O propósito aqui é reduzir repetição e aumentar legibilidade. O risco é criar utilitários compostos demais; por isso, aplique o mesmo critério de criação (uso recorrente e intenção clara).

6) Defina “zonas proibidas” para utilitários

Para evitar que utilitários virem um segundo sistema de componentes, defina limites:

  • Não criar utilitários para cores específicas de componentes (ex.: u-btn-blue).
  • Não criar utilitários para detalhes internos (ex.: u-card-title-margin).
  • Evitar utilitários para propriedades que tendem a variar muito (ex.: background-image, clip-path), salvo casos muito controlados.

Passo a passo prático: introduzindo utilitários com propósito no projeto

Passo 1 — Levante padrões reais de repetição

Faça um inventário rápido em telas e componentes existentes. Procure por:

  • mesmos espaçamentos aplicados manualmente em vários lugares;
  • mesmas regras de alinhamento e gap;
  • mesmas necessidades de truncamento, visibilidade e overflow.

O objetivo é criar utilitários para padrões recorrentes, não para preferências pessoais.

Passo 2 — Escolha um conjunto mínimo (MVP) de utilitários

Comece pequeno. Um MVP típico:

  • Espaçamento: u-m*, u-p* para 6–8 valores da escala.
  • Layout: u-flex, u-inline-flex, u-items-center, u-justify-between, u-gap-*, u-wrap.
  • Texto: u-text-center, u-truncate.
  • Visibilidade: u-hidden e 1–2 variações responsivas.

Isso já resolve grande parte dos ajustes de composição sem inflar o CSS.

Passo 3 — Implemente com tokens e gere variações de forma controlada

Mesmo sem entrar em ferramentas específicas, a regra é: utilitários devem referenciar variáveis/tokens. Exemplo de geração manual controlada:

/* Espaçamentos permitidos: 0, 2, 4, 6, 8 */
.u-mt-0 { margin-top: var(--space-0); }
.u-mt-2 { margin-top: var(--space-2); }
.u-mt-4 { margin-top: var(--space-4); }
.u-mt-6 { margin-top: var(--space-6); }
.u-mt-8 { margin-top: var(--space-8); }

.u-gap-2 { gap: var(--space-2); }
.u-gap-4 { gap: var(--space-4); }
.u-gap-6 { gap: var(--space-6); }

O ponto não é cobrir todas as combinações possíveis, e sim as necessárias e aprovadas.

Passo 4 — Defina regras de uso no code review

Crie critérios objetivos para revisão:

  • Se um ajuste aparece em um único ponto, justificar por que é utilitário e não CSS local.
  • Se um elemento tem mais de X utilitários (por exemplo, 6–8), avaliar se deveria ser um wrapper/layout específico ou um componente.
  • Se um utilitário novo é proposto, verificar se já existe equivalente e se está na escala.

Isso evita que utilitários virem “escape hatch” para qualquer coisa.

Passo 5 — Refatore duplicações conforme surgem

Ao longo do tempo, você vai encontrar:

  • utilitários que nunca são usados (candidatos a remoção);
  • utilitários usados demais em combinação fixa (candidatos a utilitário composto);
  • necessidades recorrentes fora da escala (candidatas a ajuste de tokens).

Faça pequenas correções contínuas: remover, consolidar, promover padrões. Isso mantém o sistema enxuto.

Exemplos práticos de uso (com decisões explícitas)

Exemplo 1 — Ajuste de espaçamento entre seções sem criar variação de componente

<section class="u-mb-8">
  <div class="PageHeader">...</div>
</section>

<section class="u-mb-8">
  <div class="CardList">...</div>
</section>

Aqui o utilitário tem propósito claro: padronizar espaçamento vertical entre seções com um valor da escala. Não é responsabilidade do PageHeader nem do CardList.

Exemplo 2 — Composição de header com alinhamento e gap

<header class="u-flex u-items-center u-justify-between u-gap-4">
  <div class="Brand">...</div>
  <nav class="Nav">...</nav>
</header>

Se isso aparecer em muitos lugares, promova para u-row-between. Se for um caso isolado, manter a combinação pode ser aceitável. A decisão depende da repetição real.

Exemplo 3 — Truncamento em um item de lista sem mexer no componente

<li class="ListItem">
  <span class="u-truncate">Um texto muito longo que não deve quebrar...</span>
</li>

O truncamento é um comportamento utilitário clássico: pequeno, previsível e reaproveitável.

Armadilhas comuns e como corrigir

Armadilha 1: utilitários demais por elemento

Se um elemento precisa de muitos utilitários para “parecer certo”, geralmente há um problema de modelagem: ou falta um wrapper de layout, ou o componente deveria expor uma variação/modificador, ou você está tentando montar um componente inteiro via utilitários.

Correção prática:

  • Crie um wrapper com um utilitário composto (se for padrão recorrente).
  • Ou crie/ajuste o componente para cobrir o caso de uso.

Armadilha 2: duplicação por valores quase iguais

Ex.: u-mb-6 e u-mb-7 surgem porque alguém “sentiu falta” de um meio-termo. Isso destrói consistência.

Correção prática:

  • Proibir valores fora da escala.
  • Se a escala realmente precisa de um novo passo, adicione no token e regenere utilitários de forma controlada.

Armadilha 3: utilitários que vazam para dentro do componente

Ex.: aplicar u-p-4 diretamente no elemento raiz de um componente para mudar seu “contrato” em um contexto específico. Isso pode ser válido, mas deve ser exceção, porque altera dimensões e pode quebrar alinhamentos previstos.

Correção prática:

  • Preferir aplicar utilitários em wrappers externos.
  • Se a necessidade for recorrente, criar uma variação do componente (não um utilitário novo).

Armadilha 4: utilitários que competem com estilos locais

Quando utilitários e estilos do componente brigam, o resultado é imprevisível. Isso acontece muito com propriedades como display, position, padding e width.

Correção prática:

  • Definir quais propriedades são “permitidas” para utilitários (ex.: espaçamento, alinhamento, visibilidade, overflow, truncamento).
  • Evitar utilitários para propriedades que mudam o modelo de layout do componente, a menos que seja um padrão arquitetural claro.

Agora responda o exercício sobre o conteúdo:

Qual cenário descreve melhor o uso adequado de utilitários com propósito em uma arquitetura de CSS escalável?

Você acertou! Parabéns, agora siga para a próxima página

Você errou! Tente novamente.

Utilitários com propósito servem para ajustes recorrentes e de composição, com valores controlados por tokens e comportamento previsível. Eles não devem virar uma coleção infinita de valores nem substituir componentes.

Próximo capitúlo

Exemplos progressivos antes/depois: refatoração guiada de seletores, camadas e componentes

Arrow Right Icon
Baixe o app para ganhar Certificação grátis e ouvir os cursos em background, mesmo com a tela desligada.