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

Estratégia de arquitetura com ITCSS: camadas, responsabilidades e regras de dependência

Capítulo 3

Tempo estimado de leitura: 13 minutos

+ Exercício

O que é ITCSS e por que ele resolve o “efeito bola de neve” no CSS

ITCSS (Inverted Triangle CSS) é uma estratégia de arquitetura que organiza estilos em camadas, ordenadas do mais genérico e de menor especificidade para o mais específico e de maior impacto. O “triângulo invertido” representa exatamente isso: no topo ficam regras amplas, reutilizáveis e com baixo peso; na base ficam regras pontuais, próximas do contexto de uso e com maior chance de sobrescrever algo.

A ideia central não é “criar mais arquivos”, e sim estabelecer um fluxo de dependência previsível: camadas de baixo podem depender das de cima, mas não o contrário. Isso reduz efeitos colaterais, facilita localizar onde um estilo deve morar e diminui a necessidade de “consertos” com seletores cada vez mais específicos.

ITCSS não dita um framework; ele define um sistema de camadas e regras de dependência. Você pode aplicá-lo com CSS puro, Sass, PostCSS, CSS Modules ou qualquer pipeline, desde que respeite a ordem de carregamento e as responsabilidades de cada camada.

Princípios que guiam as camadas

1) Especificidade cresce conforme você desce

Nas camadas superiores, prefira seletores simples e de baixa especificidade (elementos, classes utilitárias genéricas, variáveis). Nas camadas inferiores, você pode usar classes mais contextuais e, quando necessário, seletores mais específicos, mas sempre com intenção clara.

2) Reuso cresce conforme você sobe

Quanto mais alto, mais reutilizável e menos opinativo. Quanto mais baixo, mais “acoplado” ao contexto (um componente específico, uma página específica, um estado específico).

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

3) Dependências são unidirecionais

Uma camada só pode consumir (depender de) camadas acima. Isso evita que um componente “puxe” estilos de uma página, ou que um utilitário dependa de um componente. Quando a dependência é invertida, você cria ciclos e torna o CSS imprevisível.

4) Ordem de importação é parte da arquitetura

ITCSS funciona porque a cascata funciona. Se a ordem de carregamento estiver errada, a arquitetura quebra. Portanto, a lista de imports (ou a ordem de build) é um artefato importante do projeto.

As camadas do ITCSS: responsabilidades e exemplos

Uma divisão comum (e prática) de ITCSS é: Settings, Tools, Generic, Elements, Objects, Components e Utilities. Nem todo projeto precisa de todas, mas a lógica de “genérico → específico” deve permanecer.

Settings (Configurações)

Responsabilidade: armazenar decisões globais e estáveis, sem gerar CSS diretamente (quando possível). Aqui entram variáveis, mapas e definições que serão consumidas por outras camadas.

  • Tokens/variáveis de cor, espaçamento, tipografia (quando aplicável).
  • Breakpoints, z-index scale, durations.
  • Configurações de tema (claro/escuro) se forem apenas variáveis.
:root {  --color-bg: #ffffff;  --color-fg: #111111;  --space-1: 4px;  --space-2: 8px;  --radius-1: 6px;  --font-sans: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto;}

Regra de dependência: Settings não depende de nada. Outras camadas podem ler variáveis de Settings.

Tools (Ferramentas)

Responsabilidade: mixins, funções e helpers de pré-processador (Sass/Less) ou padrões de composição que não geram CSS por si só (ou geram apenas quando chamados). Em CSS puro, essa camada pode ser mínima ou inexistente.

  • Mixins de media queries.
  • Funções de conversão (px → rem).
  • Helpers para gerar variações.
/* Exemplo conceitual em Sass */@mixin mq($bp) {  @media (min-width: $bp) { @content; }}

Regra de dependência: Tools pode depender de Settings, mas não de camadas abaixo.

Generic (Genéricos)

Responsabilidade: estilos de base que normalizam comportamento e removem inconsistências do navegador. Aqui entram resets, normalize, box-sizing global e regras muito amplas que não descrevem “componentes”.

  • Reset/normalize.
  • Box-sizing.
  • Regras globais para mídia (img, video) que previnem overflow.
*, *::before, *::after {  box-sizing: border-box;}img, video {  max-width: 100%;  height: auto;}

Regra de dependência: Generic pode usar Settings (variáveis), mas não deve depender de componentes/objetos.

Elements (Elementos)

Responsabilidade: estilos para elementos HTML sem classes (h1, p, a, button, input). É a “pele” tipográfica e de elementos nativos, mantendo baixa especificidade.

  • Tipografia base (body, headings).
  • Links e estados de foco.
  • Estilos base de formulários.
body {  font-family: var(--font-sans);  color: var(--color-fg);  background: var(--color-bg);}a {  color: inherit;  text-decoration: underline;}button, input, select, textarea {  font: inherit;}

Regra de dependência: Elements pode depender de Settings/Generic, mas não de componentes. Evite “estilizar” elementos para parecerem um componente específico; isso deve ficar para Components.

Objects (Objetos)

Responsabilidade: padrões estruturais e de layout reutilizáveis, sem aparência específica. Objetos definem “como organiza”, não “como parece”. Normalmente são classes com baixo acoplamento visual.

  • Wrappers, containers, grids, stacks.
  • Media object (imagem + conteúdo).
  • Layouts com flex/grid genéricos.
.o-container {  width: min(1120px, 100% - 2 * var(--space-2));  margin-inline: auto;}.o-stack {  display: flex;  flex-direction: column;  gap: var(--space-2);}.o-cluster {  display: flex;  flex-wrap: wrap;  gap: var(--space-2);  align-items: center;}

Regra de dependência: Objects podem depender de Settings/Tools/Generic/Elements, mas não de Components. Um objeto não deve “conhecer” um componente específico.

Components (Componentes)

Responsabilidade: unidades de UI com aparência e comportamento visual definidos. Aqui ficam botões, cards, modais, navegação, tabelas estilizadas, etc. Componentes podem usar objetos internamente (por composição), mas não devem redefinir objetos globalmente.

  • Card, Button, Navbar, Modal.
  • Variações e estados do componente.
  • Estrutura interna com classes próprias.
.c-card {  border: 1px solid color-mix(in srgb, var(--color-fg) 15%, transparent);  border-radius: var(--radius-1);  padding: var(--space-2);  background: var(--color-bg);} .c-card__title {  font-weight: 600;  margin: 0 0 var(--space-1);} .c-card__body {  margin: 0;}

Regra de dependência: Components podem depender de Objects e de camadas acima. Um componente não deve depender de estilos de uma página específica (isso é “base” do triângulo, não “meio”).

Utilities (Utilitários)

Responsabilidade: classes pequenas, de propósito único, geralmente com alta prioridade na cascata. Utilitários existem para ajustes rápidos e previsíveis, evitando criar novos componentes ou variações só para mudar uma margem, alinhamento ou display em um ponto específico.

  • Helpers de espaçamento, display, alinhamento.
  • Visibilidade (sr-only), overflow, text truncation.
  • Overrides intencionais.
.u-hidden { display: none !important; }.u-text-center { text-align: center !important; }.u-mt-2 { margin-top: var(--space-2) !important; }

Regra de dependência: Utilities ficam por último para “ganhar” na cascata quando necessário. Eles podem usar Settings (variáveis), mas não devem depender de Components. Em geral, utilitários não devem referenciar classes de componentes (ex.: .u-fix-card { ... } seria um anti-padrão).

Regras de dependência na prática: o que pode e o que não pode

Regra 1: camadas inferiores podem sobrescrever superiores, mas não “redefinir” suas intenções

Exemplo: Elements define que links são sublinhados. Um componente pode remover o sublinhado dentro de um botão-link específico, mas isso deve acontecer dentro do escopo do componente, não alterando globalmente o elemento a.

/* Elements */a { text-decoration: underline; }/* Components */.c-buttonLink {  text-decoration: none;  display: inline-flex;  gap: var(--space-1);}

Regra 2: Objects não carregam “skin”

Se um objeto de layout começa a definir cor, sombra, borda e tipografia, ele está virando componente. Mantenha objetos focados em estrutura.

/* Bom: objeto estrutural */.o-grid {  display: grid;  gap: var(--space-2);}/* Evite: objeto com aparência */.o-grid {  background: #fff;  border: 1px solid #ddd;}

Regra 3: Utilities são explícitos e intencionais

Utilitários com !important não são “erro” por si só; são uma ferramenta de override previsível. O problema é usar utilitários para “consertar” um componente mal definido. Se você precisa de muitos utilitários para fazer um card parecer correto, o componente provavelmente precisa de uma variação formal.

Regra 4: evite seletores que atravessam camadas por acidente

Seletores como .sidebar a ou .page-home .c-card criam dependência de contexto (página) sobre componente. Em ITCSS, estilos de página (quando existirem) devem ser a última camada e muito restritos, ou preferencialmente substituídos por composição de componentes e utilitários.

/* Evite: página controlando componente */.page-home .c-card { border-color: red; }/* Prefira: variação do componente */.c-card--highlight { border-color: red; }

Passo a passo prático: implementando ITCSS em um projeto existente

Passo 1: desenhe o mapa de camadas e defina a ordem de importação

Crie uma estrutura de pastas (ou módulos) que reflita as camadas. Um exemplo simples:

styles/  settings/  tools/  generic/  elements/  objects/  components/  utilities/  main.css

No arquivo de entrada, importe na ordem do triângulo:

/* main.css */@import url('./settings/tokens.css');@import url('./generic/reset.css');@import url('./elements/base.css');@import url('./objects/layout.css');@import url('./components/card.css');@import url('./utilities/utilities.css');

Se você usa um bundler que não suporta @import nativo, a ideia é a mesma: garantir que o build concatene nessa ordem.

Passo 2: classifique o CSS atual por “intenção”, não por arquivo

Antes de mover código, classifique trechos existentes respondendo:

  • Isso é uma decisão global (variáveis)? Vai para Settings.
  • Isso normaliza comportamento do navegador? Vai para Generic.
  • Isso estiliza tags sem classe? Vai para Elements.
  • Isso é um padrão de layout reutilizável sem aparência? Vai para Objects.
  • Isso é um componente com identidade visual? Vai para Components.
  • Isso é um ajuste pontual e explícito? Vai para Utilities.

Uma forma prática é criar uma planilha/lista com “arquivo atual → camada destino” e mover por lotes pequenos.

Passo 3: reduza o escopo de regras globais que “parecem componente”

Em projetos que cresceram sem camadas, é comum encontrar algo como:

button {  background: #0b5fff;  border-radius: 8px;  padding: 12px 16px;}

Isso transforma todo <button> em um “botão do design”, o que pode ser desejado em alguns sistemas, mas geralmente vira fonte de conflito (botões de tabela, botões de modal, botões de formulário). Em ITCSS, mantenha Elements com estilos base e crie um componente:

/* Elements */button {  border: 1px solid currentColor;  background: transparent;  padding: 0;  color: inherit;}/* Components */.c-button {  background: #0b5fff;  color: white;  border: 0;  border-radius: var(--radius-1);  padding: 12px 16px;}

O passo prático aqui é: para cada regra global “opinativa”, crie um componente e migre o uso no HTML gradualmente.

Passo 4: extraia padrões de layout repetidos para Objects

Procure repetições como:

  • display: flex + gap em vários componentes.
  • Containers com a mesma largura e centralização.
  • Grids com a mesma lógica de colunas.

Crie objetos e substitua nos componentes por composição. Exemplo: em vez de cada componente definir seu próprio “stack”, use .o-stack no markup:

<div class="c-card o-stack">  <h3 class="c-card__title">Título</h3>  <p class="c-card__body">Texto</p></div>

Isso reduz duplicação e mantém o componente focado em aparência.

Passo 5: defina um conjunto mínimo de Utilities e uma política de uso

Crie utilitários para necessidades recorrentes e previsíveis. Um conjunto inicial comum:

  • Espaçamento (margens/paddings) com escala baseada em variáveis.
  • Alinhamento de texto.
  • Display helpers (block, flex, grid) se fizer sentido no seu projeto.
  • Visibilidade e acessibilidade (ex.: sr-only).

Política prática: utilitários podem ser usados no HTML para ajustes locais, mas não devem virar “dependência” de um componente para existir. Se um componente só funciona quando combinado com .u-*, isso indica que o componente está incompleto ou que você precisa de uma variação do componente.

Passo 6: crie regras para “estilos de página” (quando inevitáveis)

Alguns projetos têm páginas com necessidades únicas (landing pages, campanhas). Em ITCSS, isso deve ser tratado com extremo cuidado. Se você precisar de uma camada de “Pages”, ela deve ficar abaixo de Components e acima (ou junto) de Utilities, e deve ser altamente restrita: seletores curtos, escopo explícito, sem alterar componentes globalmente.

/* pages/home.css */.p-home {  padding-block: calc(var(--space-2) * 2);} .p-home__hero {  margin-bottom: calc(var(--space-2) * 3);}

Note que a página cria seus próprios blocos (.p-home__hero) em vez de sobrescrever .c-*. Quando precisar de um componente diferente na home, prefira variações do componente (.c-card--promo) ou composição com utilitários.

Checklist de revisão: validando se sua arquitetura está “no trilho”

Checklist por camada

  • Settings: contém apenas decisões globais (variáveis), sem seletores de UI.
  • Generic: contém reset/normalização, sem “cara” de produto.
  • Elements: estiliza tags sem classe, sem criar componentes implícitos.
  • Objects: define layout/estrutura, sem cores/sombras/skins.
  • Components: define UI com classes próprias, sem depender de páginas.
  • Utilities: classes de propósito único, com prioridade explícita quando necessário.

Sinais de violação de dependência

  • Um arquivo de componente importando um arquivo de página.
  • Um objeto usando seletores de componente (ex.: .o-grid .c-card).
  • Utilities “conhecendo” componentes (ex.: .u-fix-modal).
  • Estilos globais em Elements tentando resolver casos específicos de um componente.

Exemplo integrado: do genérico ao específico em um fluxo real

Imagine que você precisa de uma seção de “lista de produtos” com cards, grid e ajustes de espaçamento. Em ITCSS, você compõe:

  • Settings: define espaçamentos, radius, cores.
  • Objects: define o grid e o container.
  • Components: define o card de produto.
  • Utilities: faz um ajuste local de alinhamento ou margem, se necessário.
<section class="o-container u-mt-2">  <header class="o-cluster">    <h2>Produtos</h2>    <a class="c-buttonLink" href="/produtos">Ver todos</a>  </header>  <div class="o-grid" style="grid-template-columns: repeat(3, minmax(0, 1fr));">    <article class="c-card">      <h3 class="c-card__title">Produto A</h3>      <p class="c-card__body">Descrição curta.</p>    </article>  </div></section>

Mesmo sem entrar em detalhes de nomenclatura, o ponto é: layout vem de Objects, aparência vem de Components, e ajustes pontuais vêm de Utilities. A previsibilidade nasce da separação de responsabilidades e da ordem de carregamento.

Regras operacionais para times: como manter ITCSS consistente

Regra de entrada: todo novo CSS precisa de um “destino de camada”

Ao abrir um PR, a pessoa deve indicar em qual camada o estilo entra e por quê. Isso reduz a tendência de colocar tudo em “components” ou criar globais em “elements”.

Regra de revisão: proibir seletores de contexto para alterar componentes

Em revisão, marque como problema qualquer padrão do tipo:

.algum-contexto .c-componente { ... }

Substituições aceitáveis:

  • Criar uma variação do componente (.c-componente--var).
  • Compor com utilitários no HTML.
  • Criar um wrapper de página que não altere o componente, apenas organize layout.

Regra de crescimento: quando um utilitário vira recorrente, ele vira utilitário oficial

Se o time começa a repetir o mesmo ajuste em vários lugares (ex.: truncar texto, centralizar verticalmente, controlar overflow), formalize como utilitário. Isso evita “microcomponentes” criados só para um detalhe.

Regra de refatoração: quando um componente acumula muitas variações, extraia um objeto

Se um componente tem muitas variações apenas para mudar estrutura (ex.: alinhamento, distribuição, espaçamento interno), provavelmente existe um padrão estrutural escondido. Extraia para Objects e simplifique o componente para focar em skin e estados.

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

Em ITCSS, qual regra de dependência ajuda a reduzir efeitos colaterais e torna o CSS mais previsível?

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

Você errou! Tente novamente.

ITCSS define dependencias unidirecionais: o fluxo vai do generico para o especifico. Assim, camadas de baixo podem consumir as de cima, evitando ciclos e reduzindo sobrescritas imprevisiveis.

Próximo capitúlo

Estruturação de pastas e convenções de arquivos: modularização, limites e padrões de importação

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