BEM para iniciantes: por que você precisa de BEM
Publicados: 2022-03-10O BEM torna seu código escalável e reutilizável, aumentando assim a produtividade e facilitando o trabalho em equipe. Mesmo que você seja o único membro da equipe, o BEM pode ser útil para você. No entanto, muitos desenvolvedores acreditam que uma abordagem de sistema como BEM coloca limites adicionais em seu projeto e torna seu projeto sobrecarregado, pesado e lento.
Reuniremos todos os principais aspectos do BEM de forma condensada. Este artigo ajuda você a entender as ideias básicas do BEM em apenas 20 minutos e a rejeitar preconceitos de que a abordagem do sistema seja prejudicial ao seu projeto.
O Big BEM consiste em Metodologia , Tecnologias , Bibliotecas e Ferramentas . Neste artigo, falaremos mais sobre a metodologia em si, pois é a experiência concentrada de um grande número de desenvolvedores e traz uma abordagem sistemática para qualquer projeto.
Para mostrar alguns casos práticos de BEM, abordaremos as tecnologias BEM e pularemos completamente as bibliotecas e ferramentas.
Da teoria à prática:
- As principais razões pelas quais não usamos seletores, exceto classes
- Noções básicas de BEM
- Blocos e elementos
- Modificadores e misturas
- Blocos na estrutura do arquivo
- Vantagens não evidentes da metodologia
- Caso prático: BEM não é apenas para CSS
- BEM é um sistema personalizável
Então, BEM é um herói ou um vilão? Você decide! Mas antes leia o artigo.
As principais razões pelas quais não usamos seletores, exceto classes
Uma das regras básicas da metodologia BEM é usar apenas seletores de classe. Nesta seção, explicaremos o porquê.
- Por que não usamos IDs?
- Por que não usamos seletores de tags?
- Por que não usamos um seletor universal?
- Por que não usamos a redefinição de CSS?
- Por que não usamos seletores aninhados?
- Por que não combinamos uma tag e uma classe em um seletor?
- Por que não usamos seletores combinados-
- Por que não usamos seletores de atributos?
Não usamos IDs (seletores de IDs)
O ID fornece um nome exclusivo para um elemento HTML. Se o nome for exclusivo, você não poderá reutilizá-lo na interface. Isso impede que você reutilize o código.
Equívocos Comuns
- Os IDs são necessários para usar JavaScript.
Os navegadores modernos podem trabalhar com IDs ou classes. Qualquer tipo de seletor é processado na mesma taxa no navegador. - Os IDs são usados com a tag
<label>
.
Se você colocar<label>
dentro de um controle, ele não precisará de um ID. Em vez de<input id="ID"><label for="ID">Text</label>
, basta usar<label><input type="...">Text</label>
.
Não usamos seletores de tags
A marcação de página HTML é instável: um novo design pode alterar o aninhamento das seções, níveis de cabeçalho (por exemplo, de <h1>
para <h3>
) ou transformar o parágrafo <p>
na tag <div>
. Qualquer uma dessas alterações interromperá os estilos escritos para tags. Mesmo que o design não mude, o conjunto de tags é limitado. Para usar um layout existente em outro projeto, você precisa resolver conflitos entre estilos escritos para as mesmas tags.
Um conjunto estendido de tags semânticas também não pode atender a todas as necessidades de layout.
Um exemplo é quando o cabeçalho da página contém um logotipo. Um clique no logotipo abre a página principal do site ( index
). Você pode marcá-lo com tags usando a tag <img>
para a imagem e a tag <a>
para o link.
<header> <a href="/"> <img src="img.logo.png" alt="Logo"> </a> </header>
Para distinguir entre o link do logotipo e um link comum no texto, você precisa de estilos extras. Agora remova o sublinhado e a cor azul do link do logotipo:
header a { ... }
O link do logotipo não precisa ser mostrado na página principal, então altere a marcação da página de índice:
<header> <!-- the <a> tag is replaced with <span> --> <span> <img src="img.logo.png" alt="Logo"> </span> </header>
Você não precisa remover o sublinhado e a cor azul da tag <span>
. Então, vamos criar regras gerais para o link do logotipo de diferentes páginas:
header a, header span { ... }
À primeira vista, esse código parece correto, mas imagine se o designer remover o logotipo do layout. Os nomes dos seletores não ajudam a entender quais estilos devem ser removidos do projeto com o logotipo. O seletor “header a” não mostra a conexão entre o link e o logotipo. Esse seletor pode pertencer ao link no menu do cabeçalho ou, por exemplo, ao link do perfil do autor. O seletor “header span” pode pertencer a qualquer parte do cabeçalho.
Para evitar confusão, basta usar o seletor de classe de logo
para escrever os estilos de logotipo:
.logo { ... }
Não usamos redefinição de CSS
A redefinição de CSS é um conjunto de regras globais de CSS criadas para toda a página. Esses estilos afetam todos os nós de layout, violam a independência dos componentes e dificultam a sua reutilização.
No BEM, “reset” e “normalize” não são usados nem mesmo para um único bloco. A redefinição e a normalização cancelam os estilos existentes e os substituem por outros estilos, que você terá que alterar e atualizar posteriormente em qualquer caso. Como resultado, o desenvolvedor precisa escrever estilos que substituam aqueles que acabaram de ser redefinidos.
Não usamos o seletor universal ( *
)
O seletor universal indica que o projeto apresenta um estilo que afeta todos os nós do layout. Isso limita a reutilização do layout em outros projetos:
- Além disso, você deve transferir os estilos com um asterisco para o projeto. Mas neste caso, o seletor universal pode afetar os estilos no novo projeto.
- Os estilos com um asterisco devem ser adicionados ao layout que você está transferindo.
Além disso, um seletor universal pode tornar o código do projeto imprevisível. Por exemplo, pode afetar os estilos dos componentes da biblioteca universal.
Estilos comuns não economizam tempo. Muitas vezes, os desenvolvedores começam redefinindo todas as margens dos componentes ( * { margin: 0; padding: 0; }
), mas ainda as definem da mesma forma que no layout (por exemplo, margin: 12px; padding: 30px;
).
Não usamos seletores aninhados
Seletores aninhados aumentam o acoplamento de código e dificultam a reutilização do código.
A metodologia BEM não proíbe seletores aninhados, mas recomenda não usá-los muito. Por exemplo, o aninhamento é apropriado se você precisar alterar os estilos dos elementos dependendo do estado do bloco ou do tema atribuído.
.button_hovered .button__text { text-decoration: underline; } .button_theme_islands .button__text { line-height: 1.5; }
Não usamos seletores combinados
Seletores combinados são mais específicos do que seletores únicos, o que torna mais difícil redefinir blocos.
Considere o seguinte código:
<button class="button button_theme_islands">...</button>
Digamos que você defina regras CSS no seletor .button.button_theme_islands
para escrever menos. Então você adiciona o modificador “active” ao bloco:
<button class="button button_theme_islands button_active">...</button>
O seletor .button_active
não redefine as propriedades do bloco escritas como .button.button_theme_islands
porque .button.button_theme_islands
é mais específico que .button_active
. Para redefini-lo, combine o seletor do modificador de bloco com o seletor .button
e declare-o abaixo de .button.button_theme_islands
porque ambos os seletores são igualmente específicos:
.button.button_theme_islands {} .button.button_active {}
Se você usar seletores de classe simples, não terá problemas para redefinir os estilos:
.button_theme_islands {} .button_active {} .button {}
Não combinamos uma tag e uma classe em um seletor
Combinar uma tag e uma classe no mesmo seletor (por exemplo, button.button
) torna as regras CSS mais específicas, então é mais difícil redefini-las.
Considere o seguinte código:
<button class="button">...</button>
Digamos que você defina regras CSS no seletor button.button
. Então você adiciona o modificador active
ao bloco:
<button class="button button_active">...</button>
O seletor .button_active
não redefine as propriedades do bloco escrito como button.button
porque button.button
é mais específico que .button_active
. Para torná-lo mais específico, você deve combinar o seletor do modificador de bloco com a tag button.button_active
.
À medida que o projeto se desenvolve, você pode acabar com blocos com input.button
, span.button
ou a.button
. Nesse caso, todos os modificadores do bloco de button
e todos os seus elementos aninhados exigirão quatro declarações diferentes para cada instância.
Possíveis exceções
Em casos raros, a metodologia permite combinar seletores de tag e classe. Por exemplo, isso pode ser usado para definir o estilo de comentários em sistemas CMS que não podem gerar o layout correto.
Você pode usar o comentário para escrever um texto, inserir imagens ou adicionar marcação. Para torná-los compatíveis com o design do site, o desenvolvedor pode pré-definir estilos para todas as tags disponíveis para o usuário e distribuí-los em cascata para os blocos aninhados:
<div class="content"> ... <!-- the user's text --> </div> CSS rules: .content a { ... } .content p { font-family: Arial, sans-serif; text-align: center; }
Não usamos seletores de atributos
Seletores de atributo são menos informativos que seletores de classe. Como prova, considere um exemplo com um formulário de pesquisa no cabeçalho:
<header> <form action="/"> <input name="s"> <input type="submit"> </form> </header>
Tente usar atributos seletores para escrever os estilos de formulário:
header input[type=submit], header input[type=checkbox] { width: auto; margin-right: 20px; } header input[type=checkbox] { margin: 0; }
Neste exemplo, você não pode dizer com certeza pelo nome do seletor que os estilos pertencem ao formulário de pesquisa. O uso de classes torna isso mais claro. As aulas não têm restrições que impeçam você de escrever com clareza. Por exemplo, você pode escrever assim:
.form .search { ... }
Agora o código é menos ambíguo e fica claro que os estilos pertencem ao formulário de pesquisa.
Mas os seletores aninhados ainda tornam as regras CSS mais específicas e impedem que você transfira o layout entre projetos. Para se livrar do aninhamento, use os princípios BEM.
Summary : class
é o único seletor que permite isolar os estilos de cada componente do projeto; aumentar a legibilidade do código e não limitar a reutilização do layout.
O isolamento de estilos CSS é o ponto de partida mais frequente da jornada BEM. Mas isso é o mínimo que o BEM pode te dar. Para entender como os componentes independentes isolados são organizados no BEM, você precisa aprender os conceitos básicos, ou seja, Bloco, Elemento, Modificador e Mistura. Vamos fazer isso na próxima seção.
Noções básicas de BEM
- Blocos e elementos
- Modificadores e misturas
- Blocos na estrutura do arquivo
Bloco e elementos
A metodologia BEM é um conjunto de regras universais que podem ser aplicadas independentemente das tecnologias utilizadas, como CSS, Sass, HTML, JavaScript ou React.
BEM ajuda a resolver as seguintes tarefas:
- Reutilize o layout;
- Mova fragmentos de layout dentro de um projeto com segurança;
- Mova o layout finalizado entre projetos;
- Crie um código estável, previsível e claro;
- Reduza o tempo de depuração do projeto.
Em um projeto BEM, a interface consiste em blocos que podem incluir elementos. Os blocos são componentes independentes da página. Um elemento não pode existir fora do bloco, portanto, lembre-se de que cada elemento pode pertencer a apenas um bloco.
As duas primeiras letras em BEM significam fechaduras B e elementos. O nome do bloco é sempre exclusivo. Ele define o namespace para elementos e fornece uma conexão visível entre as partes do bloco. Os nomes dos blocos são longos, mas claros, para mostrar a conexão entre os componentes e evitar a perda de partes desses componentes ao transferir o layout.
Para ver todo o poder da nomenclatura BEM, considere este exemplo com um formulário. De acordo com a metodologia BEM, o formulário é implementado usando o bloco de form
. Em HTML, o nome do bloco é incluído no atributo class
:
<form class="form" action="/">
Todas as partes do formulário (o bloco de form
) que não fazem sentido por si só são consideradas seus elementos. Portanto, a caixa de pesquisa ( search
) e o botão ( submit
) são elementos do bloco de form
. As classes também indicam que um elemento pertence ao bloco:
<form class="form" action="/"> <input class="form__search" name="s"> <input class="form__submit" type="submit"> </form>
Observe que o nome do bloco é separado do nome do elemento com um separador especial. No esquema de nomenclatura clássico do BEM, dois sublinhados são usados como separador. Qualquer coisa pode funcionar como um separador. Existem convenções de nomenclatura alternativas e cada desenvolvedor escolhe a que mais lhe convém. O importante é que os separadores permitem distinguir blocos de elementos e modificadores programaticamente.
Os nomes dos seletores deixam claro que, para mover o formulário para outro projeto, você precisa copiar todos os seus componentes:
.form__search {} .form__submit {}
Usar blocos e elementos para nomes de classes resolve um problema importante: nos ajuda a nos livrar de seletores aninhados. Todos os seletores em um projeto BEM têm o mesmo peso. Isso significa que é muito mais fácil redefinir estilos escritos de acordo com o BEM. Agora, para usar o mesmo formulário em outro projeto, basta copiar seu layout e estilos.
A ideia da nomenclatura dos componentes BEM é que você pode definir explicitamente a conexão entre o bloco e seus elementos.
Modificadores e misturas
Oficialmente, “ M ” significa modificador, mas também implica mais uma noção importante no BEM: “mix”. Ambos os modificadores e mixagens fazem alterações em um bloco e seus elementos. Vamos dar uma olhada nisso.
Modificadores
Um modificador define a aparência, estado e comportamento de um bloco ou elemento. A adição de modificadores é opcional. Os modificadores permitem combinar diferentes recursos de bloco, pois você pode usar qualquer número de modificadores. Mas um bloco ou um elemento não pode receber valores diferentes do mesmo modificador.
Vamos explorar como os modificadores funcionam.
Imagine que o projeto precisa do mesmo formulário de pesquisa do exemplo acima. Deve ter as mesmas funções, mas ter uma aparência diferente (por exemplo, os formulários de pesquisa no cabeçalho e no rodapé da página devem ser diferentes). A primeira coisa que você pode fazer para alterar a aparência do formulário é escrever estilos adicionais:
header .form {} footer .form {}
O seletor header .form
tem mais peso que o seletor de form
, o que significa que uma regra substituirá a outra. Mas, como discutimos, seletores aninhados aumentam o acoplamento de código e dificultam a reutilização, portanto, essa abordagem não funciona para nós.
No BEM, você pode usar um modificador para adicionar novos estilos ao bloco:
<!-- Added the form_type_original modifier--> <form class="form form_type_original" action="/"> <input class="form__search" name="s"> <input class="form__submit" type="submit"> </form>
A linha <form class="form form_type_original"></form>
indica que o bloco recebeu um modificador de type
com o valor original
. Em um esquema clássico, o nome do modificador é separado do nome do bloco ou elemento com um sublinhado.
O formulário pode ter uma cor, tamanho, tipo ou tema de design exclusivo. Todos esses parâmetros podem ser definidos com um modificador:
<form class="form form_type_original form_size_m form_theme_forest">
<form class="form form_type_original form_size_m form_theme_forest">
A mesma forma pode parecer diferente, mas permanecer do mesmo tamanho:
<form class="form form_type_original form_size_m form_theme_forest"></form> <form class="form form_type_original form_size_m form_theme_sun"></form>
Mas os seletores para cada modificador ainda terão o mesmo peso:
.form_type_original {} .form_size_m {} .form_theme_forest {}
Importante : Um modificador contém apenas estilos adicionais que alteram a implementação do bloco original de alguma forma. Isso permite definir a aparência de um bloco universal apenas uma vez e adicionar apenas os recursos que diferem do código de bloco original nos estilos do modificador.
.form { /* universal block styles */ } .form_type_original { /* added styles */ }
É por isso que um modificador deve estar sempre no mesmo nó DOM com o bloco e o elemento ao qual está associado.
<form class="form form_type_original"></form>
Você pode usar modificadores para aplicar componentes universais em casos muito específicos. O código do bloco e do elemento não muda. A combinação necessária de modificadores é criada no nó DOM.
Misturas
Uma mistura permite aplicar a mesma formatação a diferentes elementos HTML e combinar o comportamento e os estilos de várias entidades, evitando a duplicação de código. Eles podem substituir blocos de wrapper abstratos.
Uma combinação significa que você hospeda várias entidades BEM (blocos, elementos, modificadores) em um único nó DOM. Semelhante aos modificadores, as misturas são usadas para alterar os blocos. Vejamos alguns exemplos de quando você deve usar uma mixagem.
Os blocos podem diferir não apenas visualmente, mas também semanticamente. Por exemplo, um formulário de pesquisa, um formulário de registro e um formulário para encomenda de bolos são todos formulários. No layout, eles são implementados com o bloco “form”, mas não possuem estilos em comum. É impossível lidar com tais diferenças com um modificador. Você pode definir estilos comuns para esses blocos, mas não poderá reutilizar o código.
.form, .search, .register { ... }
Você pode usar uma mistura para criar blocos semanticamente diferentes para o mesmo formulário:
<form class="form" action="/"> <input class="form__search" name="s"> <input class="form__submit" type="submit"> </form>
O seletor de classe .form
descreve todos os estilos que podem ser aplicados a qualquer formulário (pedido, pesquisa ou registro):
.form {}
Agora você pode fazer um formulário de pesquisa do formulário universal. Para fazer isso, crie uma classe de search
adicional no projeto. Esta classe será responsável apenas pela pesquisa. Para combinar os estilos e o comportamento das classes .form
e .search
, coloque essas classes em um único nó DOM:
<form class="form search" action="/"> <input class="form__search" name="s"> <input class="form__submit" type="submit"> </form>
Nesse caso, a classe .search
é um bloco separado que define o comportamento. Este bloco não pode ter modificadores responsáveis pelo formulário, temas e tamanhos. Esses modificadores já pertencem à forma universal. Uma mistura ajuda a combinar os estilos e o comportamento desses blocos.
Vamos dar mais um exemplo onde a semântica do componente é alterada. Aqui está um menu de navegação no cabeçalho da página em que todas as entradas são links:
<nav class="menu"> <a class="link" href=""></a> <a class="link" href=""></a> <a class="link" href=""></a> </nav>
A funcionalidade de link já está implementada no bloco de link
, mas os links do menu devem ser visualmente diferentes dos links no texto. Existem várias maneiras de alterar os links do menu:
- Crie um modificador de entrada de menu que transforme a entrada em um link:
<nav class="menu"> <a class="menu__item menu__item_link" href=""></a> <a class="menu__item menu__item_link" href=""></a> <a class="menu__item menu__item_link" href=""></a> </nav>
Neste caso, para implementar o modificador, você deve copiar o comportamento e os estilos do bloco `link`. Isso levará à duplicação de código. - Use uma mistura do bloco universal `link` e do elemento `item` do bloco `menu`:
<nav class="menu"> <a class="link menu__item" href=""></a> <a class="link menu__item" href=""></a> <a class="link menu__item" href=""></a> </nav>
Com a combinação das duas entidades BEM, agora você pode implementar a funcionalidade básica de link do bloco `link` e regras CSS adicionais do bloco `menu` e evitar a duplicação de código.
Geometria externa e posicionamento: desistindo dos wrappers HTML abstratos
As misturas são usadas para posicionar um bloco em relação a outros blocos ou para posicionar elementos dentro de um bloco. No BEM, os estilos responsáveis pela geometria e posicionamento são definidos no bloco pai. Vamos pegar um bloco de menu universal que deve ser colocado no cabeçalho. No layout, o bloco deve ter um recuo de 20px do bloco pai.
Esta tarefa tem várias soluções:
- Escreva estilos com recuos para o bloco de menu:
.menu { margin-left: 20px; }
Nesse caso, o bloco "menu" não é mais universal. Se você tiver que colocar o menu no rodapé da página, terá que editar os estilos porque os recuos provavelmente serão diferentes. - Crie o modificador de bloco de menu:
<div> <ul class="menu menu_type_header"> <li class="menu__item"><a href=""></a></li> <li class="menu__item"><a href=""></a></li> <li class="menu__item"><a href=""></a></li> </ul> </div>
.menu_type_header { margin-left: 20px; } .menu_type_footer { margin-left: 30px; }
Neste caso, o projeto incluirá dois tipos de menus, embora não seja o caso. O cardápio continua o mesmo. - Defina o posicionamento externo do bloco: aninhe o bloco `menu` no wrapper abstrato (por exemplo, o bloco `wrap`) definindo todos os recuos:
<div class="wrap"> <ul class="menu"> <li class="menu__item"><a href=""></a></li> <li class="menu__item"><a href=""></a></li> <li class="menu__item"><a href=""></a></li> </ul> </div>
Para evitar a tentação de criar modificadores e alterar os estilos de bloco para posicionar o bloco na página, você precisa entender uma coisa:O recuo de um bloco pai não é um recurso do bloco aninhado. É um recurso do bloco pai. Ele precisa saber que o bloco aninhado deve ser recuado da borda por um certo número de pixels.
- Use uma mistura. As informações sobre o posicionamento do bloco aninhado estão incluídas nos elementos do bloco pai. Em seguida, o elemento do bloco pai é misturado no bloco aninhado. Nesse caso, o bloco aninhado não especifica nenhum recuo e pode ser facilmente reutilizado em qualquer lugar.
Vamos continuar com nosso exemplo:
<div> <ul class="menu header__menu"> <li class="menu__item"><a href=""></a></li> <li class="menu__item"><a href=""></a></li> <li class="menu__item"><a href=""></a></li> </ul> </div>
Neste caso, a geometria externa e o posicionamento do bloco de menu
são definidos através do elemento header__menu
. O bloco de menu
não especifica nenhum recuo e pode ser facilmente reutilizado.
O elemento do bloco pai (no nosso caso é header__menu
) executa a tarefa dos blocos wrapper responsáveis pelo posicionamento externo do bloco.
Blocos na estrutura do arquivo
Todos os projetos BEM têm uma estrutura de arquivos semelhante. A estrutura de arquivo familiar torna mais fácil para os desenvolvedores navegar no projeto, alternar entre projetos e mover blocos de um projeto para outro.
A implementação de cada bloco é armazenada em uma pasta de projeto separada. Cada tecnologia (CSS, JavaScript, testes, modelos, documentação, imagens) está em um arquivo separado.
Por exemplo, se a aparência do bloco de input
for definida com CSS, o código será salvo no arquivo input.css
.
project common.blocks/ input/ input.css # The "input" block implementation with CSS input.js # The "input" block implementation with JavaScript
O código para modificadores e elementos também é armazenado em arquivos separados do bloco. Essa abordagem permite incluir na compilação apenas os modificadores e elementos necessários para a implementação do bloco.
project common.blocks/ input/ input.css # The "input" block implementation with CSS input.js # The "input" block implementation with JavaScript input_theme_sun.css # The "input_theme_sun" modifier implementation input__clear.css # The "input__clear" element implementation with CSS input__clear.js # The "input__clear" element implementation with JavaScript
Para melhorar a navegação do projeto, combine modificadores de bloco com vários valores em diretórios.
A estrutura de arquivos de qualquer projeto BEM consiste em níveis de redefinição (você pode aprender mais sobre eles aqui). Os níveis de redefinição permitem:
- Divida o projeto em plataformas;
- Atualize facilmente as bibliotecas de blocos incluídas no projeto;
- Use blocos comuns para desenvolver vários projetos;
- Altere os temas de design sem afetar a lógica do projeto;
- Conduza experimentos em um projeto ao vivo.
Usar blocos e armazenar todas as tecnologias de bloco na mesma pasta facilita a movimentação de blocos entre projetos. Para mover todos os estilos e comportamento do bloco junto com o layout, basta copiar a pasta do bloco para o novo projeto.
Vantagens não evidentes da metodologia
A conveniência do desenvolvimento paralelo
No BEM, qualquer layout é dividido em blocos. Como os blocos são independentes, eles podem ser desenvolvidos em paralelo por vários desenvolvedores.
Um desenvolvedor cria um bloco como um componente universal que pode ser reutilizado em qualquer outro projeto.
Um exemplo é a biblioteca de blocos bem-components, que contém blocos universais, como link, botão e campo de entrada. É mais fácil criar blocos mais complexos a partir de componentes universais. Por exemplo, um seletor ou caixa de seleção.
O uso de blocos no layout do projeto ajuda a economizar tempo na integração de código escrito por vários desenvolvedores, garante a exclusividade dos nomes dos componentes e permite testar blocos no estágio de desenvolvimento.
Testando o layout
É problemático testar a funcionalidade de toda a página, especialmente em um projeto dinâmico conectado a um banco de dados.
No BEM, cada bloco é coberto por testes. Os testes são uma tecnologia de implementação de blocos, como Javascript ou CSS. Os blocos são testados na fase de desenvolvimento. É mais fácil verificar a exatidão de um bloco e depois montar o projeto a partir de blocos testados. Depois disso, tudo o que você precisa fazer é garantir que o wrapper de bloco esteja funcionando corretamente.
Construção personalizável de um projeto
Para um desenvolvimento conveniente, todos os blocos e tecnologias em um projeto BEM são colocados em pastas e arquivos separados. Para combinar os arquivos de origem em um único arquivo (por exemplo, para colocar todos os arquivos CSS em project.css
, todos os arquivos JS em project.js
e assim por diante), usamos o processo de compilação.
A compilação executa as seguintes tarefas:
- Combina arquivos de origem que estão espalhados pelo sistema de arquivos do projeto;
- Inclui apenas blocos, elementos e modificadores necessários (entidades BEM) no projeto;
- Segue a ordem de inclusão de entidades;
- Processa o código do arquivo fonte durante a compilação (por exemplo, compila menos código para código CSS).
Para incluir apenas as entidades BEM necessárias na compilação, você precisa criar uma lista de blocos, elementos e modificadores usados nas páginas. Essa lista é chamada de declaração .
Como os blocos BEM são desenvolvidos independentemente e colocados em arquivos separados no sistema de arquivos, eles não 'sabem' nada um do outro. Para construir blocos com base em outros blocos, especifique as dependências. Existe uma tecnologia BEM responsável por isso: os arquivos deps.js
Os arquivos de dependência permitem que o mecanismo de construção saiba quais blocos adicionais devem ser incluídos no projeto.
Caso prático: BEM não é apenas para CSS
Nas seções anteriores, todos os exemplos de código são para CSS. Mas o BEM permite modificar o comportamento do bloco e sua representação em HTML da mesma forma declarativa como em CSS.
Como usar o modelo no BEM
Em HTML, a marcação do bloco é repetida toda vez que o bloco aparece na página. Se você criar a marcação HTML manualmente e precisar corrigir um erro ou fazer alterações, será necessário modificar a marcação para cada instância do bloco. Para gerar código HTML e aplicar correções automaticamente, o BEM usa templates; os blocos são responsáveis pela forma como são apresentados em HTML.
Os modelos permitem que você:
- Reduza o tempo de depuração do projeto, pois as alterações do template são aplicadas automaticamente a todos os blocos do projeto;
- Modifique o layout do bloco;
- Mova os blocos com o layout atual para outro projeto.
O BEM usa o mecanismo de modelo bem-xjst que possui dois mecanismos:
- BEMHTML
Transforma a descrição BEMJSON da página em HTML. Os modelos são descritos em arquivos .bemhtml.js. - BEMTREE
Transforma dados em BEMJSON. Os modelos são descritos no formato BEMJSON em arquivos .bemtree.js.
Se os modelos não forem escritos para os blocos, o mecanismo de modelo define a tag <div>
para os blocos por padrão.
Compare a declaração dos blocos e a saída HTML:
Declaração:
{ block: 'menu', content: [ { elem: 'item', content: { block: 'link'} }, { elem: 'item', elemMods: { current: true }, // Set the modifier for the menu item content: { block: 'link' } } ] }
HTML:
<div class="menu"> <div class="menu__item"> <div class="link"></div> </div> <div class="menu__item menu__item_current"> <div class="link"></div> </div> </div>
Para modificar o layout do bloco de menu
, você precisa escrever modelos para o bloco:
- Vamos alterar a tag do bloco de
menu
:block('menu')( tag()('menu') // Set the "menu" tag for the menu block )
HTML modificado:<menu class="menu"> <!-- Replace the "div" tag with the "menu" tag for the "menu" block --> <div class="menu__item"> <div class="link"></div> </div> <div class="menu__item menu__item_current"> <div class="link"></div> </div> </menu>
Semelhante ao CSS, o modelo é aplicado a todos os blocos de "menu" na página. - Adicione um elemento extra (
menu__inner
) que funciona como um wrapper interno e é responsável pelo layout dos elementos no bloco demenu
. Originalmente o elementomenu__inner
não foi incluído na declaração, então temos que adicioná-lo quando os templates são construídos.
Os modelos BEM são escritos em JavaScript, portanto, você também pode usar JavaScript para adicionar um novo elemento ao modelo:block('menu')( tag()('menu'), content()(function() { return { elem: 'inner', content: this.ctx.content }; }) )
<menu class="menu"> <!-- Replace the "div" tag with the "menu" tag for the "menu" block --> <div class="menu__inner"> <div class="menu__item"> <div class="link"></div> </div> <div class="menu__item menu__item_current"> <div class="link"></div> </div> </div> </menu>
- Substitua as tags para todos os elementos
inner
e deitem
:block('menu')( tag()('menu'), content()(function() { return { elem: 'inner', content: this.ctx.content } }), elem('inner')( tag()('ul') ), elem('item')( tag()('li') ) )
<menu class="menu"> <ul class="menu__inner"> <li class="menu__item"> <div class="link"></div> </li> <li class="menu__item menu__item_current"> <div class="link"></div> </li> </ul> </menu>
- Defina a tag
<a>
para todos os links na página:block('menu')( tag()('menu'), content()(function() { return { elem: 'inner', content: this.ctx.content } }), elem('inner')( tag()('ul') ), elem('item')( tag()('li') ) ); block('link')( tag()('a') );
<menu class="menu"> <ul class="menu__inner"> <li class="menu__item"> <a class="link"></a> </li> <li class="menu__item menu__item_current"> <a class="link"></a> </li> </ul> </menu>
- Modifique o modelo existente. As regras nos modelos são aplicadas da mesma forma que no CSS: uma regra inferior substitui uma regra superior. Adicione novas regras ao modelo e altere a tag do link de
<a>
para<span>
:block('link')( tag()('a') ); block('link')( tag()('span') );
<menu class="menu"> <ul class="menu__inner"> <li class="menu__item"> <span class="link"></span> </li> <li class="menu__item menu__item_current"> <span class="link"></span> </li> </ul> </menu>
BEM é um sistema personalizável
A metodologia BEM fornece regras rígidas para criar um sistema em seu projeto. Mas, ao mesmo tempo, muitas regras BEM podem ser personalizadas. A metodologia BEM permite que você altere a convenção de nomenclatura, escolha a estrutura de arquivos mais conveniente ou adicione quaisquer tecnologias que desejar ao bloco.
Agora você pode sintonizar o sistema e fazer o seu próprio super-herói do BEM!
Como tirar mais proveito do BEM
Para começar a aprender os princípios do BEM, visite nosso site. Se você tiver alguma dúvida que gostaria de fazer à equipe, junte-se ao nosso canal do Telegram ou abra uma discussão em nosso Fórum BEM.