DEV Community

Adriana Ferreira Lima Shikasho
Adriana Ferreira Lima Shikasho

Posted on • Edited on

[pt-BR] Como padronizar a nomenclatura de classes utilizando o CSS Pattern BEM

A metodologia Block, Element, Modifier (comumente chamada de BEM) é o nome popular de um CSS Pattern ou convenção de classes que tem como objetivo ajudar os desenvolvedores a entender melhor a relação entre o HTML e o CSS de um projeto.

Entretanto, antes de tratarmos do BEM, vamos entender o porque é interessante utilizar uma convenção para o CSS.

Entendendo especificidade do CSS

A melhor maneira de introduzir o assunto é por um exemplo onde um css muito específico pode causar confusão e fazer com que seu código não se comporte da maneira que você gostaria.

Aqui temos uma lista simples e não ordenada:



<ul id="summer-drinks">
   <li>Água</li>
   <li>Coca-cola</li>
   <li>Suco de Laranja</li>
</ul>


Enter fullscreen mode Exit fullscreen mode

Agora, para identificar uma dessas bebidas como a favorita, vamos modificar seu estilo por meio de uma classe no elemento da lista.



<ul id="summer-drinks">
   <li class="favorite">Água</li>
   <li>Coca-cola</li>
   <li>Suco de Laranja</li>
</ul>


Enter fullscreen mode Exit fullscreen mode

Agora incluímos a classe com o estilo no css:



.favorite {
  color: red;
  font-weight: bold;
}


Enter fullscreen mode Exit fullscreen mode

Aí percebemos que ao olhar na tela, a estilização não funcionou! O que será que deu de errado? Ao fuçar no css, encontramos isso aqui:



ul#summer-drinks li {
   font-weight: normal;
   font-size: 12px;
   color: black;
}


Enter fullscreen mode Exit fullscreen mode

Aí está nosso problema. Temos 2 seletores diferentes dizendo qual a cor e peso da fonte o elemento deve ter. E também temos 1 declaração do tamanho da fonte, que com certeza está afetando a lista.

Esses não são "conflitos" por assim dizer, mas o navegador vai ter que de alguma forma decidir qual dessas declarações ele vai utilizar. Ele faz isso seguindo um conjunto padrão de regras de especificidade como por exemplo escolher aquele que está "mais abaixo" ou o último a ser declarado:



.favorite {
   color: red;
}
.favorite {
   color: black;
}


Enter fullscreen mode Exit fullscreen mode

A cor será preta e... ok!

Entretanto, nem sempre será seguro usar dessa forma, justamente porque pode haver esse conflito do que vem antes ou do que vem depois. Uma forma para evitar é ser ainda mais específico, e ficaria assim:



ul#summer-drinks li.favorite {
  color: red;
  font-weight: bold;
}


Enter fullscreen mode Exit fullscreen mode

ou assim:



html body div#pagewrap ul#summer-drinks li.favorite {
  color: red;
  font-weight: bold;
}


Enter fullscreen mode Exit fullscreen mode

Ta bom, vamos combinar que isso é demais não é? Temos que admitir essas formas acabam tornando nosso CSS cada vez mais difícil de ler e não traz benefícios reais.

Talvez nem precisamos falar muito daqueles momentos em que precisamos forçar a estilização com o !important e no fim, vira mais uma gambiarra que pode trazer algumas dores de cabeça no futuro.

Por fim, conseguimos chegar a conclusão que quanto mais especificidade no css, mas difícil será sua manutenção a longo prazo, e provavelmente não é isso que nós queremos pra o projeto.

Existem algumas formas de calcular o nível de especificidades de seletores do css: Atributo Style, ID, classes, pseudo-classes e elementos, mas acho que isso está a kilometros de distância de ser algo prático na vida do dev. Mas em resumo seria algo do tipo:

Image description

Obs: os créditos da imagem estão no rodapé desse artigo

E é nesse momento que convenções como o BEM atuam para nos ajudar a lidar com isso. Pensando no fato que o BEM trabalha no nível de classes, percebemos que ele realmente tem um nível de especificidade baixo, o que é uma boa solução pros problemas apresentados em seleções de alta especificidade, não é mesmo?

Voltando ao BEM

Logo de cara, podemos dizer que uma das principais vantagens da utilização do BEM é que mesmo se um desenvolvedor não estiver familiarizado com o CSS daquele código que ele vai mexer, só a leitura da marcação HTML já dá uma boa ideia da responsabilidade de cada classe e da relação de dependência entre elas.

Abaixo temos um exemplo de um código CSS que segue padrão BEM:



/* Componente Bloco */
.btn {}

/* Elemento que depende do bloco */ 
.btn__price {}

/* Modificador que estiliza o bloco */
.btn--orange {} 


Enter fullscreen mode Exit fullscreen mode

Bloco (Block)

Nessa metodologia CSS, um bloco é a abstração máxima de um novo componente, e é entendido como um "item-pai". Por exemplo um button: .btn {}.

Elemento (Element)

Os elementos são os "itens-filhos" que ficarão dentro da tag pai e são denotados com dois underscores seguidos do nome do bloco como por exemplo .btn__price {}.

Modificadores (Modifiers)

Por fim, os modificadores são manipuladores dos blocos para adicionar alguma estilização específica àquele componente e sem influenciar algum módulo que não estiver relacionado. Ele é escrito com dois hífens depois do nome do bloco como por exemplo .btn--orange.

O código ficaria algo assim:



<button class="btn btn--big btn--orange">
  <span class="btn__price">$9.99</span>
  <span class="btn__text">Subscribe</span>
</button>


Enter fullscreen mode Exit fullscreen mode

Aplicação do padrão BEM

Aqui temos um exemplo de como a combinação de classes que usam a metodologia BEM, podem tornar a estilização muito mais fácil.



<button class="btn">
  <span class="btn__text">Standard button</span>
</button>

<button class="btn btn--orange btn--big">
  <span class="btn__price">$3</span>
  <span class="btn__text">Big button</span>
</button>

<button class="btn btn--blue btn--big">
  <span class="btn__price">$4</span>
  <span class="btn__text">Big button</span>
</button>



Enter fullscreen mode Exit fullscreen mode


/* Bloco */
.btn {
  background-color: white;
  color: #888;
  font-size: 18px;
  padding: 10px 5px;
}

/* Elemento */
.btn__price {
  background-color: red;
  color: #fff;
  padding: 0 12px;
}

/* Elemento */
.btn__text {
  padding: 0 10px;
}

/* Modificador */
.btn--big {
  font-size: 28px;
  padding: 10px;
}

/* Modificador */
.btn--blue {
  color: white;
  background-color: #0074D9;
}

/* Modificador */
.btn--orange {
  color: white;
  background-color: #FF4136;
}


Enter fullscreen mode Exit fullscreen mode

4 vantanges na utilização do CSS Pattern BEM

Vamos ver agora alguns benefícios que a utilização que uma metodologia como BEM pode trazer ao projeto e aos desenvolvedores.

Entretanto, acredito que essas vantagens serão descritas, não se aplicam apenas a essa metodologia, mas as demais também podem trazer as mesmas vantagens, em níveis diferentes.

Vamos lá!

1. Reutilização de classes pré-existentes e diminuição de CSS legado

Antes mesmo de criar um novo estilo para um bloco, podemos facilmente verificar quais os modificadores já existem no projeto. Caso já exista um que te atenda, não será necessário criar outro o que contribui para evitar css legado ou desconhecido.

2. Relação de dependência intuitiva

Ao ler o código HTML, já é possível entender rapidamente qual elemento depende de qual, e replicar isso de maneira fácil nas outras partes do projeto. Como no exemplo anterior em o .btn__price depende de .btn como sendo seu "item-pai".

3. Melhora a comunicação do time

Os componentes serão nomeados de forma que facilite a comunicação entre os designers, desenvolvedores e outros membros do time. Em outras palavras, o BEM vai permitir trabalhar com uma sintaxe declarativa a ser compartilhada e permitir que todos estejam na mesma página.

4. Desenvolvimento e manutenção com mais confiança

A utilização do BEM contribui para que os desenvolvedores tenham menos receio de fazer mudanças no código por não saberem o quanto aquilo pode afetar outros módulos. No BEM, tudo é classe e terá muito menos acoplamento.

Isso é chamado de "low CSS specificity" (css com baixa especificidade) o que na prática significa talvez um css que seja mais "genérico", e ajuda a evitar conflitos entre seletores e estilizações. Vamos falar um pouco mais sobre isso no próximo tópico, pois vai nos ajudar a entender um pouco mais da aplicação do BEM no dia-a-dia.

Método BEM e outros métodos

Existem diversos outros métodos de padronização de marcação e estilos além do BEM, como o SMACSS e o OOCSS.

No SMACSS, é provável encontrar um nome de classe com 3 letras, e os modificadores seguem o nome do módulo com um hífen:



/* Módulo */
.btn { }

/* Modificador*/
.btn-primary { }

/* Módulo com Estado */
.btn.is-collapsed { }


Enter fullscreen mode Exit fullscreen mode

É uma abordagem interessante também para atender o mesmo tipo de problema que o BEM atende. É bastante semelhante e também permite ser mais explícito quanto as dependências, e ainda sim mantendo a especificidade baixa.

O padrão OOCSS, também possui blocos geneéricos, entretanto, é necessário utilizar várias classes no HTML para definir as variações e os elementos internos não são nomeados como se tivesse dependência, tornando menos clara a leitura, mas potencialmente mais reutilizável:



/* Módulo */
.mod { }

/* Parte do Módulo */
.inner { }

/* Módulo Talk */
.talk { }

/* Variação da parte interna do Módulo Talk*/
.talk .inner { }

Enter fullscreen mode Exit fullscreen mode




Conclusão

Pra utilizar convenções é necessário avaliar com calma seus pontos positivos e negativos, sempre pensando em facilitar o trabalho e onerar menos.

Ao optar pelo BEM, algumas pessoas podem acabar não gostando de utilizar underscores e traços duplos e não vejo isso como um problema, porque eu mesma sou uma delas rs.

Entretanto, achei interessante a abordagem do BEM e acho que tudo bem aplicá-lo com algumas modificações, assim como tudo bem as vezes quebrar alguma regra dele.

O mais importante acredito, é definir o método e usá-lo de forma mais consistente possível em todo o projeto, avaliando muito bem cada exceção.

Referências utilizadas:

CSS-tricks: "BEM 101", Robin Rendle
https://css-tricks.com/bem-101/

CSS-tricks: "Specifics on CSS Specificity", Chris Couier
https://css-tricks.com/specifics-on-css-specificity/

Top comments (0)