Pular para o conteúdo
Cursos

DevClub

LógicaFront-endBack-endMobile

IA Club

IA na prática
Estudar programaçãoEstudar IA
LiçãoIntermediáriocódigo testado

@apply no Tailwind: como usar e quando não usar

O @apply transforma um punhado de utilitários numa classe só. Onde isso ajuda de verdade, onde devolve o problema do CSS antigo e o que fazer no lugar.

Rodolfo Mori4 min de leitura

@apply copia declarações de utilitários para um seletor CSS seu. Ele é útil na fronteira com markup que você não controla e em uma regra pequena compartilhada; não é o caminho obrigatório para “limpar” atributos longos.

O teste desta lição compilou quatro botões idênticos de duas maneiras. O resultado medido mostra que tamanho de bundle não decide sozinho; arquitetura e localidade do estilo pesam mais.

O compilador expande a lista linha por linha

Uma classe criada no CSS pode aplicar utilitários conhecidos:

css
.botao {
  @apply rounded-lg bg-cyan-600 px-4 py-2 font-bold text-white;
}

O CLI produziu CSS comum:

css
.botao {
  border-radius: var(--radius-lg);
  background-color: var(--color-cyan-600);
  padding-inline: calc(var(--spacing) * 4);
  padding-block: calc(var(--spacing) * 2);
  font-weight: var(--font-weight-bold);
  color: var(--color-white);
}

O navegador não recebe @apply. O trabalho termina no build.

Use quando a fronteira não aceita classes

Conteúdo de terceiros pode entregar uma classe fixa, como .botao-compra, sem permitir editar o HTML. Uma camada local com @apply adapta a saída ao sistema:

css
.widget-pagamento .botao-compra {
  @apply rounded-lg bg-cyan-600 px-4 py-2 font-bold text-white;
}

Outro caso é uma regra pequena que precisa participar de CSS comum:

css
.conteudo a {
  @apply font-medium text-cyan-700 underline;
}

Use seletor com alcance explícito. .btn global em toda aplicação vira uma API informal que qualquer equipe pode ampliar sem contrato.

O problema volta quando a abstração cresce sem dono

Uma classe começa com seis utilitários, depois recebe tamanho, variante, ícone, loading e exceções. O HTML fica curto, mas a decisão volta a ficar distante.

css
.btn { @apply rounded-lg px-4 py-2 font-bold; }
.btn-primary { @apply bg-cyan-600 text-white hover:bg-cyan-700; }
.btn-danger { @apply bg-rose-600 text-white hover:bg-rose-700; }
.btn-small { @apply px-2 py-1 text-sm; }

Quando combinações viram props e estados, isso já é componente. Extraia markup, acessibilidade e comportamento juntos. A lição de componentes Tailwind em React mostra essa fronteira.

Variantes podem aparecer no @apply

O compilador aceita variantes conhecidas na lista. Ainda assim, um seletor explícito às vezes comunica melhor a relação.

css
.botao {
  @apply bg-cyan-600 hover:bg-cyan-700 focus-visible:outline-2;
}
css
.botao:hover { background: var(--color-cyan-700); }
.botao:focus-visible { outline-width: 2px; }

Escolha a forma que o time consegue depurar. O objetivo não é usar Tailwind em toda linha do CSS; é manter o sistema coerente.

Utility desconhecida interrompe o build

Aplicar um token que não existe gera erro. Reproduzi com bg-clinica-500 sem declarar --color-clinica-500:

css
.cartao {
  @apply bg-clinica-500;
}
bash
npx @tailwindcss/cli -i unknown.css -o unknown-output.css
Error: ┌ │ Error: Cannot apply unknown utility class `bg-clinica-500` └

O erro é útil: ele prova que o problema está no build, não na cascata do navegador. Declare o token em @theme ou corrija o nome.

Em CSS Modules, referência de tema exige cuidado

Cada módulo é processado separadamente e não conhece automaticamente o contexto de tema da folha principal. A documentação recomenda evitar misturar Tailwind e CSS Modules sem necessidade. Se precisar referenciar utilidades no módulo, importe a referência adequada ou prefira variáveis CSS comuns.

css
/* Cartao.module.css */
.raiz {
  color: var(--color-slate-900);
}

Não importe todo o Tailwind em cada módulo: isso multiplica processamento e pode duplicar CSS. Uma integração gradual pode manter módulos existentes e usar utilities no markup novo.

Quatro repetições não aumentaram as regras utility

Na versão de markup, quatro botões repetiram a mesma string. O compilador emitiu cada utilitário uma vez. Na versão @apply, uma .btn reuniu as declarações.

html
<button class="rounded-lg bg-cyan-600 px-4 py-2 font-bold text-white hover:bg-cyan-700">
  Salvar
</button>
bash
wc -c apply-markup.out.css apply-component.out.css
4990 apply-markup.out.css 4912 apply-component.out.css 9902 total

Em gzip, foram 1.767 contra 1.736 bytes. @apply ficou 31 bytes menor neste caso. Isso não prova que ele é sempre menor: seletor, variantes, Preflight e tema mudam o resultado. Prova apenas que repetir classes no HTML não repete as regras no CSS final.

Três alternativas antes de criar uma classe global

Se o markup se repete com responsabilidade própria, extraia componente. Se só um valor varia em runtime, use variável CSS. Se você precisa reduzir especificidade de um seletor comum, use :where().

html
<button class="bg-(--cor-acao) text-white" style="--cor-acao:#0891b2">
  Salvar
</button>

Valores externos precisam ser validados antes de entrar em style. Uma variável resolve valor dinâmico; não tente montar bg-${cor}-600, porque o scanner não executa JavaScript.

Regra de decisão

Eu uso @apply quando preciso levar tokens Tailwind a um seletor CSS que já é a interface de integração. Para componentes que controlo, deixo utilities no markup e extraio um componente quando a repetição ganha comportamento. Essa regra preserva a vantagem de ler estilo e estrutura juntos.

Sua missão é compilar os quatro botões nas duas formas, medir cru e gzip, depois adicionar uma variante de erro. Explique qual arquivo ficou mais fácil de alterar sem abrir exceção. Compare a decisão com o benchmark Tailwind, CSS puro e Modules antes de transformar um resultado pequeno em regra universal.

Revise a fronteira seis meses depois

Procure seletores com @apply e classifique-os: integração externa, conteúdo gerado, primitiva visual ou componente disfarçado. Os dois primeiros costumam continuar bons. Primitivas e componentes merecem revisão, porque podem ter acumulado variantes, estados e exceções que o seletor não expressa bem.

Conte quantos lugares importam a folha e quantos componentes usam a classe. Uma regra global carregada por todo o produto para atender uma tela rara pode ser movida para a rota. Uma string utility repetida em vários arquivos pode indicar componente ausente. Nenhuma contagem decide sozinha; ela aponta onde ler.

Verifique também tokens de referência. Um @apply bg-marca pode parar de funcionar quando o módulo é processado fora do contexto de tema. Prefira variável CSS comum quando só precisa consumir um valor, e reserve @reference ou integração específica para casos documentados da ferramenta. Não importe o framework completo num módulo apenas para satisfazer uma declaração.

Ao final, registre uma regra curta no manual do projeto: quais fronteiras aceitam @apply, quem aprova uma classe global e como medir o artefato. O guia da trilha transforma essa decisão local em parte do sistema, evitando que cada revisão reabra a mesma disputa abstrata.

  • tailwind
  • apply
  • css
  • componentes
  • manutenção

Dúvidas e comentários

Travou em algum passo? Pergunte aqui — a equipe e outros alunos respondem.

Todo o código deste artigo foi executado em @tailwindcss/cli 4.3.3 no Node 26.3.0, com gzip -9, e as saídas exibidas são as reais — como produzimos este conteúdo.

Fontes consultadas

  1. Tailwind CSS — Functions and directives — tailwindcss.com
  2. Tailwind CSS — Compatibility with CSS Modules — tailwindcss.com

Continue por aqui