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

Nomeação consistente com BEM: blocos, elementos, modificadores e variações seguras

Capítulo 6

Tempo estimado de leitura: 12 minutos

+ Exercício

O que significa “nomeação consistente” em BEM

BEM (Block, Element, Modifier) é uma convenção de nomes para classes CSS que torna explícito o papel de cada seletor e o escopo em que ele deve atuar. “Nomeação consistente” significa que, ao ler uma classe, você consegue responder rapidamente: (1) qual é o componente principal (bloco), (2) qual parte interna desse componente está sendo estilizada (elemento) e (3) qual variação de aparência/estado está sendo aplicada (modificador). A consistência vem de aplicar as mesmas regras em todo o projeto, evitando sinônimos, abreviações aleatórias e padrões misturados.

Em BEM, a classe é o contrato. Ela descreve a intenção e reduz a necessidade de seletores complexos. Quando a equipe segue o mesmo padrão, o CSS fica mais previsível: você sabe onde procurar estilos, como estender um componente e como evitar “efeitos colaterais” ao criar variações.

Vocabulário BEM: bloco, elemento e modificador

Bloco (Block)

O bloco é a unidade independente de interface: um componente que faz sentido por si só. Exemplos típicos: card, button, modal, navbar, product. Um bloco deve ser nomeado como um substantivo (ou sintagma nominal) que represente o componente, e não sua posição na página.

  • Bom: .card, .product-list, .search-form
  • Evite: .left-column, .blue-box, .homepage-card (acopla o componente ao contexto)

Elemento (Element)

Elemento é uma parte interna do bloco, que depende dele para fazer sentido. A sintaxe clássica é bloco__elemento. Elementos não existem “soltos”: se você vê __title sem o bloco, é um sinal de que o nome está incompleto ou que o elemento deveria ser um bloco próprio.

  • Exemplos: .card__title, .card__content, .modal__header, .modal__close
  • Evite: .title dentro de muitos componentes (genérico demais) ou .card__left quando “left” é apenas layout circunstancial

Modificador (Modifier)

Modificador é uma variação do bloco ou do elemento. A sintaxe clássica é bloco--modificador ou bloco__elemento--modificador. Modificadores devem representar uma diferença relevante e previsível: tamanho, aparência, densidade, ênfase, estado ou variante de comportamento visual.

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

  • Exemplos de bloco: .button--primary, .card--outlined, .modal--fullscreen
  • Exemplos de elemento: .button__icon--left, .card__title--truncate

Um ponto central para variações seguras: o modificador não deve “redefinir” o componente inteiro de forma imprevisível. Ele deve alterar um conjunto pequeno e intencional de propriedades, mantendo o contrato do bloco.

Regras práticas de nomeação (para evitar ambiguidades)

1) Use nomes semânticos, não visuais

Prefira nomes que descrevam função e papel, não cor, pixel ou posição. Isso reduz retrabalho quando o design muda.

  • Bom: .alert--success, .badge--warning
  • Evite: .alert--green, .badge--yellow

2) Padronize idioma, separadores e pluralização

Escolha um idioma para os nomes (por exemplo, inglês) e mantenha. Defina também se você usa hífen (product-card) ou camelCase (productCard) para blocos. Em BEM, hífen é o mais comum e combina bem com __ e --.

  • Consistente: .product-card, .product-card__price, .product-card--compact
  • Inconsistente: .produtoCard, .product-card__preco, .productCard--compact

3) Evite abreviações não óbvias

Abreviações economizam caracteres, mas custam entendimento. Se a equipe não concorda imediatamente no significado, não use.

  • Bom: .navigation, .navigation__item
  • Evite: .nav (pode ser aceitável se for padrão do time), .nvg (opaco)

4) Não encode hierarquia de DOM no nome

BEM já expressa relação bloco-elemento. Evite nomes que dependem da estrutura exata do HTML, como __list-item-link para representar profundidade. Se a profundidade importa, talvez você esteja descrevendo elementos demais ou misturando responsabilidades.

  • Preferível: .menu__item e dentro dele .menu__link
  • Evite: .menu__list__item__link (não é BEM e tende a ficar frágil)

5) Elementos devem ser “partes”, não “variantes”

Se algo é uma variação do componente, use modificador. Se é uma parte estrutural, use elemento. Misturar isso gera confusão e CSS duplicado.

  • Parte: .card__footer
  • Variação: .card--with-footer (se a presença/estilo do footer muda o layout do card inteiro)

Variações seguras: como criar modificadores sem quebrar o componente

“Variação segura” é uma variação que não exige conhecer o contexto externo para funcionar e não cria dependências ocultas. Em BEM, isso se traduz em modificadores que:

  • Alteram poucas propriedades e de forma previsível.
  • Não dependem de seletores de contexto como .sidebar .button para “consertar” aparência.
  • Não mudam a estrutura esperada do componente (por exemplo, não exigem que um elemento exista em um lugar específico para o CSS funcionar).
  • Não introduzem efeitos colaterais em elementos não relacionados.

Modificadores de “tema” vs. modificadores de “estado”

Uma forma prática de manter variações seguras é separar mentalmente dois tipos comuns:

  • Tema/variante visual: --primary, --secondary, --danger, --outlined, --ghost.
  • Estado: --is-loading, --is-disabled, --is-active.

Você pode padronizar prefixos para estados (por exemplo, is-) para deixar claro que são temporários e normalmente controlados por JS ou por atributos. Exemplo:

<button class="button button--primary button--is-loading" type="button">Salvar</button>

Note que o estado é um modificador do bloco. Isso evita criar classes genéricas como .is-loading que podem vazar e afetar qualquer coisa.

Evite modificadores que mudam “demais”

Um anti-padrão comum é usar um modificador para transformar um componente em outro. Exemplo: .card--modal ou .button--link quando o resultado se comporta como outro componente com regras próprias. Nesse caso, considere criar um novo bloco (.modal, .link-button) ou um bloco base com composição.

Passo a passo prático: modelando um componente com BEM

Vamos construir um componente de “Card de produto” com variações seguras. O objetivo é mostrar como decidir nomes e como estruturar modificadores sem criar dependências frágeis.

Passo 1: Defina o bloco e seu propósito

O componente representa um produto com imagem, título, preço e ações. Nome do bloco: product-card. Evite card se o projeto tiver muitos tipos de card com contratos diferentes; nesse caso, ser específico ajuda.

<article class="product-card"></article>

Passo 2: Liste elementos internos que são partes estáveis

Elementos devem ser partes que provavelmente existirão em qualquer instância do componente (ou, se opcionais, ainda fazem sentido como parte do bloco).

<article class="product-card">  <a class="product-card__media" href="/produto/123">    <img class="product-card__image" src="product.jpg" alt="Tênis">  </a>  <div class="product-card__body">    <h3 class="product-card__title">Tênis X</h3>    <p class="product-card__price">R$ 199,90</p>  </div>  <div class="product-card__actions">    <button class="button button--primary" type="button">Comprar</button>  </div></article>

Repare que o botão é outro bloco (button) sendo composto dentro do product-card. Isso é uma prática saudável: cada bloco mantém seu contrato, e o card apenas organiza.

Passo 3: Crie modificadores de variante (visuais) com escopo claro

Suponha duas variantes: “compacto” e “destaque”. Elas alteram espaçamentos e ênfase, mas não mudam a estrutura.

<article class="product-card product-card--compact">...</article> <article class="product-card product-card--featured">...</article>

No CSS, o modificador deve alterar apenas o necessário. Exemplo:

.product-card {  display: grid;  gap: 12px;  padding: 16px;  border-radius: 12px;} .product-card--compact {  gap: 8px;  padding: 12px;} .product-card--featured {  border: 2px solid var(--color-accent);}

Observe que --featured não redefine layout inteiro; ele adiciona uma borda de destaque. Isso é uma variação segura.

Passo 4: Crie modificadores de estado sem acoplar ao DOM

Agora um estado: indisponível. Esse estado pode afetar imagem, preço e botão, mas deve ser controlado pelo bloco, não por seletores externos.

<article class="product-card product-card--is-unavailable">...</article>
.product-card--is-unavailable {  opacity: 0.6;} .product-card--is-unavailable .product-card__actions {  pointer-events: none;}

Esse exemplo usa um seletor descendente dentro do próprio bloco, o que é aceitável quando você está restringindo o efeito a elementos do mesmo bloco. O cuidado é não criar dependência de contexto externo; aqui, tudo permanece dentro do contrato do product-card.

Passo 5: Quando o modificador é do elemento (e não do bloco)

Algumas variações são locais a um elemento. Exemplo: título truncado em uma linha apenas em certas listagens. Em vez de criar um modificador do bloco que afeta o título, você pode modificar o próprio elemento:

<h3 class="product-card__title product-card__title--truncate">Tênis X Edição Limitada...</h3>
.product-card__title--truncate {  white-space: nowrap;  overflow: hidden;  text-overflow: ellipsis;}

Isso é seguro porque a variação é claramente local e não altera o restante do componente.

Como lidar com “variações por contexto” sem quebrar BEM

Um problema recorrente é precisar de um componente com aparência diferente quando usado em uma área específica (ex.: dentro de um header, dentro de um sidebar). A abordagem frágil é escrever CSS do tipo .sidebar .product-card { ... }, porque isso cria dependência do local e dificulta reutilização.

Em BEM, prefira uma destas estratégias:

  • Modificador explícito: o contexto aplica uma classe de modificador no componente, como product-card--in-sidebar. Isso torna a dependência visível no HTML.
  • Bloco “wrapper” com composição: crie um bloco para o contexto (ex.: sidebar) e, se necessário, use uma classe de utilidade ou um modificador no componente para ajustes mínimos.
  • Nova variante do componente: se o “mesmo” componente muda muito, é sinal de que são dois componentes diferentes. Crie um novo bloco com contrato próprio.

Exemplo com modificador explícito:

<aside class="sidebar">  <article class="product-card product-card--in-sidebar">...</article></aside>

O nome --in-sidebar é aceitável quando o ajuste é realmente contextual e pequeno. Se começar a acumular muitos contextos (--in-header, --in-footer, --in-modal), reavalie o design do componente.

Checklist de consistência: decisões que o time deve padronizar

Para que BEM funcione em projetos reais, é útil transformar decisões em regras simples. Abaixo um checklist que você pode adotar como padrão interno.

Formato e caracteres

  • Blocos em minúsculas com hífen: product-card.
  • Elemento com __: product-card__title.
  • Modificador com --: product-card--featured.
  • Sem underscores simples (_) para não confundir com __.

Estados

  • Estados como modificadores do bloco: --is-loading, --is-disabled, --is-open.
  • Evitar estados globais genéricos (.is-open) a menos que exista uma camada de utilitários bem definida e controlada.

Variações

  • Modificadores descrevem “o que muda” (ex.: --compact, --outlined), não “como é implementado” (ex.: --grid se o usuário não precisa saber disso).
  • Evitar modificadores com múltiplos significados (ex.: --special, --new).

Elementos opcionais

  • Elementos opcionais podem existir, mas o bloco não deve quebrar se eles não estiverem presentes.
  • Se um elemento opcional vira “um componente dentro do componente” com regras próprias, considere promovê-lo a bloco (composição).

Armadilhas comuns e como corrigir

Armadilha 1: “Elemento de elemento”

Em BEM clássico, não existe block__element__subelement. Se você sente necessidade disso, geralmente é um sinal de que:

  • Você está descrevendo a estrutura do DOM em vez de papéis.
  • Um elemento complexo deveria ser um bloco interno.

Exemplo de correção por composição:

<div class="card">  <div class="card__header">    <div class="user-badge">      <img class="user-badge__avatar" ...>      <span class="user-badge__name">...</span>    </div>  </div></div>

Armadilha 2: Modificador usado como bloco

Exemplo: criar .button--primary e usar sem .button. Isso quebra o contrato, porque o modificador pressupõe a base do bloco.

  • Correto: class="button button--primary"
  • Incorreto: class="button--primary"

Se você quer uma classe única para o caso, então primary-button seria outro bloco (mas normalmente é melhor manter o padrão de base + modificador).

Armadilha 3: Modificadores em cascata que viram “combinações explosivas”

Quando você cria muitos modificadores que interagem entre si, o número de combinações cresce e fica difícil garantir consistência. Exemplo: --compact + --featured + --with-badge + --horizontal. Para manter variações seguras:

  • Defina quais modificadores podem coexistir.
  • Evite modificadores que mudam o “tipo” do componente (ex.: vertical vs horizontal) se isso exigir reescrever muitos estilos; considere variantes separadas ou um novo bloco.
  • Quando coexistirem, mantenha regras simples e previsíveis (por exemplo, --compact só mexe em espaçamento).

Armadilha 4: Nomes que viram “lixeira”

Classes como --custom, --alt, --v2 geralmente indicam falta de critério. Troque por nomes que expliquem intenção:

  • --alt--outlined ou --subtle
  • --v2--dense, --compact, --with-icon (o que realmente mudou?)

Guia rápido de decisão: isso é bloco, elemento ou modificador?

Use estas perguntas para decidir rapidamente:

  • É reutilizável sozinho e tem significado independente? Então é um bloco.
  • É uma parte interna que só faz sentido dentro do componente? Então é um elemento.
  • É uma variação de aparência/estado do bloco ou do elemento, sem criar um “novo componente”? Então é um modificador.

Exemplo aplicado:

  • modal (bloco)
  • modal__header (elemento)
  • modal--fullscreen (modificador do bloco)
  • modal__close--hidden (modificador do elemento, se for uma variação local)

Exemplo completo: componente de formulário com variações seguras

Agora um exemplo que costuma gerar CSS inconsistente: campo de texto com ícone, mensagem de erro e tamanhos.

<div class="field field--md">  <label class="field__label" for="email">E-mail</label>  <div class="field__control">    <span class="field__icon" aria-hidden="true"></span>    <input class="field__input" id="email" type="email">  </div>  <p class="field__message"></p></div>

Variações seguras:

  • Tamanho: field--sm, field--md, field--lg (muda padding, font-size, altura do input).
  • Estado de erro: field--is-invalid (muda borda e mostra mensagem).
  • Sem ícone: field--no-icon (ajusta padding do input).
<div class="field field--sm field--is-invalid">  ...  <p class="field__message">E-mail inválido</p></div>

Note que o estado de erro está no bloco, porque afeta múltiplos elementos internos. Já uma variação como “truncar mensagem” poderia ser um modificador do elemento field__message--truncate se fosse algo local.

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

Qual opção segue corretamente o princípio de variações seguras em BEM para indicar um estado temporário sem criar uma classe global genérica?

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

Você errou! Tente novamente.

Em BEM, estados temporários devem ser modificadores do bloco (ex.: --is-loading), mantendo o contrato do componente e evitando classes globais genéricas que podem vazar e afetar outros elementos.

Próximo capitúlo

Mapeamento de componentes para BEM: estados, temas, tamanhos e composição sem cascata frágil

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