BEM per principianti: perché hai bisogno di BEM
Pubblicato: 2022-03-10BEM rende il tuo codice scalabile e riutilizzabile, aumentando così la produttività e facilitando il lavoro di squadra. Anche se sei l'unico membro del team, BEM può esserti utile. Tuttavia, molti sviluppatori ritengono che un tale approccio di sistema come BEM ponga ulteriori limiti al loro progetto e renda il tuo progetto sovraccarico, ingombrante e lento.
Raccoglieremo tutti gli aspetti principali di BEM in forma condensata. Questo articolo ti aiuta a comprendere le idee di base del BEM in soli 20 minuti e a respingere i pregiudizi secondo cui l'approccio di sistema è dannoso per il tuo progetto.
Il Big BEM è costituito da Metodologia , Tecnologie , Biblioteche e Strumenti . In questo articolo parleremo di più della metodologia stessa perché è l'esperienza concentrata di un numero enorme di sviluppatori e porta un approccio sistematico a qualsiasi progetto.
Per mostrarti alcuni casi pratici di BEM, toccheremo le tecnologie BEM e salteremo completamente le librerie e gli strumenti.
Dalla teoria alla pratica:
- I motivi principali per cui non utilizziamo alcun selettore tranne le classi
- Le basi di BEM
- Blocchi ed elementi
- Modificatori E Mix
- Blocchi nella struttura del file
- Vantaggi non evidenti della metodologia
- Caso pratico: BEM non è solo per CSS
- BEM è un sistema personalizzabile
Quindi, BEM è un eroe o un cattivo? Tocca a voi! Ma prima leggi l'articolo.
I motivi principali per cui non utilizziamo alcun selettore tranne le classi
Una delle regole di base della metodologia BEM è quella di utilizzare solo selettori di classe. In questa sezione spiegheremo perché.
- Perché non usiamo gli ID?
- Perché non utilizziamo i selettori di tag?
- Perché non utilizziamo un selettore universale?
- Perché non usiamo il ripristino CSS?
- Perché non usiamo selettori nidificati?
- Perché non combiniamo un tag e una classe in un selettore?
- Perché non usiamo selettori combinati-
- Perché non utilizziamo i selettori di attributi?
Non utilizziamo ID (selettori ID)
L'ID fornisce un nome univoco per un elemento HTML. Se il nome è univoco, non puoi riutilizzarlo nell'interfaccia. Ciò impedisce di riutilizzare il codice.
Idee sbagliate comuni
- Gli ID sono necessari per utilizzare JavaScript.
I browser moderni possono funzionare con ID o classi. Qualsiasi tipo di selettore viene elaborato alla stessa velocità nel browser. - Gli ID vengono utilizzati con il tag
<label>
.
Se inserisci<label>
all'interno di un controllo, non è necessario un ID. Invece di<input id="ID"><label for="ID">Text</label>
, usa semplicemente<label><input type="...">Text</label>
.
Non utilizziamo selettori di tag
Il markup della pagina HTML è instabile: un nuovo design può modificare l'annidamento delle sezioni, i livelli di intestazione (ad esempio, da <h1>
a <h3>
) o trasformare il paragrafo <p>
nel tag <div>
. Qualsiasi di queste modifiche interromperà gli stili scritti per i tag. Anche se il design non cambia, il set di tag è limitato. Per utilizzare un layout esistente in un altro progetto, devi risolvere i conflitti tra gli stili scritti per gli stessi tag.
Anche un set esteso di tag semantici non può soddisfare tutte le esigenze di layout.
Un esempio è quando l'intestazione della pagina contiene un logo. Un click sul logo apre la pagina principale del sito ( index
). Puoi contrassegnarlo con i tag utilizzando il tag <img>
per l'immagine e il tag <a>
per il collegamento.
<header> <a href="/"> <img src="img.logo.png" alt="Logo"> </a> </header>
Per distinguere tra il collegamento del logo e un normale collegamento nel testo, sono necessari stili aggiuntivi. Ora rimuovi la sottolineatura e il colore blu dal link del logo:
header a { ... }
Non è necessario che il link del logo sia mostrato nella pagina principale, quindi modifica il markup della pagina dell'indice:
<header> <!-- the <a> tag is replaced with <span> --> <span> <img src="img.logo.png" alt="Logo"> </span> </header>
Non è necessario rimuovere la sottolineatura e il colore blu per il tag <span>
. Quindi stabiliamo le regole generali per il collegamento del logo da diverse pagine:
header a, header span { ... }
A prima vista, questo codice sembra a posto, ma immagina se il designer rimuove il logo dal layout. I nomi del selettore non ti aiutano a capire quali stili dovrebbero essere rimossi dal progetto con il logo. Il selettore “header a” non mostra il collegamento tra il link e il logo. Questo selettore potrebbe appartenere al link presente nel menu di intestazione o, ad esempio, al link al profilo dell'autore. Il selettore "header span" potrebbe appartenere a qualsiasi parte dell'intestazione.
Per evitare confusione, usa il selettore di classe del logo
per scrivere gli stili del logo:
.logo { ... }
Non utilizziamo il ripristino CSS
CSS reset è un insieme di regole CSS globali create per l'intera pagina. Questi stili influiscono su tutti i nodi di layout, violano l'indipendenza dei componenti e rendono più difficile il loro riutilizzo.
In BEM, "reset" e "normalize" non vengono nemmeno utilizzati per un singolo blocco. Il ripristino e la normalizzazione annullano gli stili esistenti e li sostituiscono con altri stili, che in ogni caso dovrai modificare e aggiornare successivamente. Di conseguenza, lo sviluppatore deve scrivere stili che sovrascrivono quelli che sono stati appena reimpostati.
Non utilizziamo il selettore universale ( *
)
Il selettore universale indica che il progetto presenta uno stile che interessa tutti i nodi del layout. Ciò limita il riutilizzo del layout in altri progetti:
- Devi anche trasferire gli stili con un asterisco nel progetto. Ma in questo caso, il selettore universale potrebbe influenzare gli stili nel nuovo progetto.
- Gli stili con un asterisco devono essere aggiunti al layout che stai trasferendo.
Inoltre, un selettore universale può rendere imprevedibile il codice del progetto. Ad esempio, può influenzare gli stili dei componenti della libreria universale.
Gli stili comuni non ti fanno risparmiare tempo. Spesso gli sviluppatori iniziano reimpostando tutti i margini per i componenti ( * { margin: 0; padding: 0; }
), ma poi li impostano come nel layout (ad esempio, margin: 12px; padding: 30px;
).
Non utilizziamo selettori nidificati
I selettori annidati aumentano l'accoppiamento del codice e rendono difficile il riutilizzo del codice.
La metodologia BEM non vieta i selettori nidificati, ma consiglia di non usarli troppo. Ad esempio, l'annidamento è appropriato se è necessario modificare gli stili degli elementi in base allo stato del blocco o al tema assegnato.
.button_hovered .button__text { text-decoration: underline; } .button_theme_islands .button__text { line-height: 1.5; }
Non utilizziamo selettori combinati
I selettori combinati sono più specifici dei selettori singoli, il che rende più difficile ridefinire i blocchi.
Considera il seguente codice:
<button class="button button_theme_islands">...</button>
Diciamo che imposti le regole CSS nel selettore .button.button_theme_islands
per scrivere meno. Quindi aggiungi il modificatore "attivo" al blocco:
<button class="button button_theme_islands button_active">...</button>
Il selettore .button_active
non ridefinisce le proprietà del blocco scritte come .button.button_theme_islands
perché .button.button_theme_islands
è più specifico di .button_active
. Per ridefinirlo, combinare il selettore del modificatore di blocco con il selettore .button
e dichiararlo sotto .button.button_theme_islands
perché entrambi i selettori sono ugualmente specifici:
.button.button_theme_islands {} .button.button_active {}
Se utilizzi semplici selettori di classe, non avrai problemi a ridefinire gli stili:
.button_theme_islands {} .button_active {} .button {}
Non combiniamo un tag e una classe in un selettore
La combinazione di un tag e di una classe nello stesso selettore (ad esempio, button.button
) rende le regole CSS più specifiche, quindi è più difficile ridefinirle.
Considera il seguente codice:
<button class="button">...</button>
Supponiamo che tu imposti le regole CSS nel selettore button.button
. Quindi aggiungi il modificatore active
al blocco:
<button class="button button_active">...</button>
Il selettore .button_active
non ridefinisce le proprietà del blocco scritte come button.button
perché button.button
è più specifico di .button_active
. Per renderlo più specifico, dovresti combinare il selettore del modificatore di blocco con il tag button.button_active
.
Man mano che il progetto si sviluppa, potresti ritrovarti con blocchi con input.button
, span.button
o a.button
. In questo caso, tutti i modificatori del blocco button
e tutti i suoi elementi nidificati richiederanno quattro diverse dichiarazioni per ciascuna istanza.
Possibili eccezioni
In rari casi, la metodologia consente di combinare tag e selettori di classe. Ad esempio, questo può essere utilizzato per impostare lo stile dei commenti nei sistemi CMS che non possono generare il layout corretto.
Puoi usare il commento per scrivere un testo, inserire immagini o aggiungere markup. Per farli corrispondere al design del sito, lo sviluppatore può predefinire gli stili per tutti i tag disponibili per l'utente e collegarli a cascata ai blocchi nidificati:
<div class="content"> ... <!-- the user's text --> </div> CSS rules: .content a { ... } .content p { font-family: Arial, sans-serif; text-align: center; }
Non utilizziamo selettori di attributi
I selettori di attributo sono meno informativi dei selettori di classe. Come prova, considera un esempio con un modulo di ricerca nell'intestazione:
<header> <form action="/"> <input name="s"> <input type="submit"> </form> </header>
Prova a utilizzare gli attributi del selettore per scrivere gli stili del modulo:
header input[type=submit], header input[type=checkbox] { width: auto; margin-right: 20px; } header input[type=checkbox] { margin: 0; }
In questo esempio, dal nome del selettore non puoi dire con certezza che gli stili appartengono al modulo di ricerca. L'uso delle classi lo rende più chiaro. Le lezioni non hanno restrizioni che ti impediscono di scrivere in modo chiaro. Ad esempio, puoi scriverlo in questo modo:
.form .search { ... }
Ora il codice è meno ambiguo ed è chiaro che gli stili appartengono al form di ricerca.
Ma i selettori nidificati rendono ancora più specifiche le regole CSS e impediscono di trasferire il layout tra i progetti. Per eliminare la nidificazione, utilizzare i principi BEM.
Riepilogo : class
è l'unico selettore che permette di isolare gli stili di ogni componente del progetto; aumentare la leggibilità del codice e non limitare il riutilizzo del layout.
L'isolamento degli stili CSS è il punto di partenza più frequente del viaggio BEM. Ma questo è il minimo che BEM può darti. Per capire come sono disposti i componenti indipendenti e isolati in BEM, è necessario apprendere i concetti di base, ovvero Block, Element, Modifier e Mix. Facciamolo nella prossima sezione.
Le basi di BEM
- Blocchi ed elementi
- Modificatori E Mix
- Blocchi nella struttura del file
Blocco ed elementi
La metodologia BEM è un insieme di regole universali che possono essere applicate indipendentemente dalle tecnologie utilizzate, come CSS, Sass, HTML, JavaScript o React.
BEM aiuta a risolvere i seguenti compiti:
- Riutilizza il layout;
- Sposta i frammenti di layout all'interno di un progetto in modo sicuro;
- Sposta il layout finito tra i progetti;
- Crea codice stabile, prevedibile e chiaro;
- Riduci il tempo di debug del progetto.
In un progetto BEM, l'interfaccia è costituita da blocchi che possono includere elementi. I blocchi sono componenti indipendenti della pagina. Un elemento non può esistere al di fuori del blocco, quindi tieni presente che ogni elemento può appartenere a un solo blocco.
Le prime due lettere in BEM stanno per blocchi B ed elementi E. Il nome del blocco è sempre univoco. Imposta lo spazio dei nomi per gli elementi e fornisce una connessione visibile tra le parti del blocco. I nomi dei blocchi sono lunghi ma chiari per mostrare la connessione tra i componenti ed evitare di perdere parti di questi componenti durante il trasferimento del layout.
Per vedere tutta la potenza della denominazione BEM, considera questo esempio con un modulo. Secondo la metodologia BEM, il modulo viene implementato utilizzando il blocco form
. In HTML, il nome del blocco è incluso nell'attributo class
:
<form class="form" action="/">
Tutte le parti del modulo (il blocco form
) che non hanno senso di per sé sono considerate suoi elementi. Quindi la casella di ricerca ( search
) e il pulsante ( submit
) sono elementi del blocco form
. Le classi indicano anche che un elemento appartiene al blocco:
<form class="form" action="/"> <input class="form__search" name="s"> <input class="form__submit" type="submit"> </form>
Nota che il nome del blocco è separato dal nome dell'elemento con un separatore speciale. Nello schema di denominazione classico BEM, due trattini bassi vengono utilizzati come separatori. Tutto può funzionare come separatore. Esistono convenzioni di denominazione alternative e ogni sviluppatore sceglie quella che gli si addice. L'importante è che i separatori ti permettano di distinguere i blocchi dagli elementi e dai modificatori a livello di codice.
I nomi dei selettori chiariscono che per spostare il modulo in un altro progetto, è necessario copiare tutti i suoi componenti:
.form__search {} .form__submit {}
L'uso di blocchi ed elementi per i nomi delle classi risolve un problema importante: ci aiuta a sbarazzarci dei selettori nidificati. Tutti i selettori in un progetto BEM hanno lo stesso peso. Ciò significa che è molto più facile ridefinire gli stili scritti secondo BEM. Ora, per utilizzare lo stesso modulo in un altro progetto, puoi semplicemente copiarne il layout e gli stili.
L'idea della denominazione dei componenti BEM è che è possibile definire esplicitamente la connessione tra il blocco ei suoi elementi.
Modificatori E Mix
Ufficialmente, " M " sta per Modifier, ma implica anche un'altra nozione importante in BEM: "mix". Sia i modificatori che i mix apportano modifiche a un blocco e ai suoi elementi. Diamo un'occhiata più da vicino a questo.
Modificatori
Un modificatore definisce l'aspetto, lo stato e il comportamento di un blocco o di un elemento. L'aggiunta di modificatori è facoltativa. I modificatori ti consentono di combinare diverse funzioni di blocco, poiché puoi utilizzare un numero qualsiasi di modificatori. Ma a un blocco oa un elemento non possono essere assegnati valori diversi dello stesso modificatore.
Esploriamo come funzionano i modificatori.
Immagina che il progetto necessiti dello stesso modulo di ricerca dell'esempio sopra. Dovrebbe avere le stesse funzioni ma avere un aspetto diverso (ad esempio, i moduli di ricerca nell'intestazione e nel piè di pagina della pagina dovrebbero essere diversi). La prima cosa che puoi fare per cambiare l'aspetto del modulo è scrivere stili aggiuntivi:
header .form {} footer .form {}
Il selettore header .form
ha più peso del selettore form
, il che significa che una regola sostituirà l'altra. Ma come abbiamo discusso, i selettori nidificati aumentano l'accoppiamento del codice e rendono difficile il riutilizzo, quindi questo approccio non funziona per noi.
In BEM, puoi utilizzare un modificatore per aggiungere nuovi stili al blocco:
<!-- 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>
La riga <form class="form form_type_original"></form>
indica che al blocco è stato assegnato un modificatore di type
con il valore original
. In uno schema classico, il nome del modificatore è separato dal nome del blocco o dell'elemento con un trattino basso.
Il modulo può avere un colore, una dimensione, un tipo o un tema di progettazione univoci. Tutti questi parametri possono essere impostati con un modificatore:
<form class="form form_type_original form_size_m form_theme_forest">
<form class="form form_type_original form_size_m form_theme_forest">
La stessa forma può avere un aspetto diverso ma rimanere della stessa dimensione:
<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>
Ma i selettori per ogni modificatore avranno ancora lo stesso peso:
.form_type_original {} .form_size_m {} .form_theme_forest {}
Importante : un modificatore contiene solo stili aggiuntivi che modificano in qualche modo l'implementazione del blocco originale. Ciò consente di impostare l'aspetto di un blocco universale solo una volta e di aggiungere solo le funzionalità che differiscono dal codice del blocco originale negli stili di modifica.
.form { /* universal block styles */ } .form_type_original { /* added styles */ }
Questo è il motivo per cui un modificatore dovrebbe trovarsi sempre sullo stesso nodo DOM con il blocco e l'elemento a cui è associato.
<form class="form form_type_original"></form>
È possibile utilizzare i modificatori per applicare componenti universali in casi molto specifici. Il codice del blocco e dell'elemento non cambia. La necessaria combinazione di modificatori viene creata sul nodo DOM.
Miscele
Un mix consente di applicare la stessa formattazione a diversi elementi HTML e combinare il comportamento e gli stili di diverse entità evitando la duplicazione del codice. Possono sostituire i blocchi di wrapper astratti.
Un mix significa che ospiti diverse entità BEM (blocchi, elementi, modificatori) su un singolo nodo DOM. Simile ai modificatori, i mix sono usati per cambiare i blocchi. Diamo un'occhiata ad alcuni esempi di quando dovresti usare un mix.
I blocchi possono differire non solo visivamente ma anche semanticamente. Ad esempio, un modulo di ricerca, un modulo di registrazione e un modulo per l'ordinazione di torte sono tutti moduli. Nel layout sono implementati con il blocco “form” ma non hanno stili in comune. È impossibile gestire tali differenze con un modificatore. Puoi definire stili comuni per tali blocchi ma non sarai in grado di riutilizzare il codice.
.form, .search, .register { ... }
Puoi usare un mix per creare blocchi semanticamente diversi per lo stesso modulo:
<form class="form" action="/"> <input class="form__search" name="s"> <input class="form__submit" type="submit"> </form>
Il selettore di classe .form
descrive tutti gli stili che possono essere applicati a qualsiasi modulo (ordine, ricerca o registrazione):
.form {}
Ora puoi creare un modulo di ricerca dal modulo universale. Per fare ciò, crea una classe di search
aggiuntiva nel progetto. Questa classe sarà responsabile solo della ricerca. Per combinare gli stili e il comportamento delle classi .form
e .search
, posiziona queste classi su un singolo nodo DOM:
<form class="form search" action="/"> <input class="form__search" name="s"> <input class="form__submit" type="submit"> </form>
In questo caso, la classe .search
è un blocco separato che definisce il comportamento. Questo blocco non può avere modificatori responsabili del modulo, dei temi e delle dimensioni. Questi modificatori appartengono già alla forma universale. Un mix aiuta a combinare gli stili e il comportamento di questi blocchi.
Facciamo un altro esempio in cui viene modificata la semantica del componente. Ecco un menu di navigazione nell'intestazione della pagina in cui tutte le voci sono collegamenti:
<nav class="menu"> <a class="link" href=""></a> <a class="link" href=""></a> <a class="link" href=""></a> </nav>
La funzionalità di collegamento è già implementata nel blocco di link
, ma i collegamenti di menu devono differire visivamente dai collegamenti nel testo. Esistono diversi modi per modificare i collegamenti del menu:
- Crea un modificatore di voce di menu che trasforma la voce in un collegamento:
<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>
In questo caso, per implementare il modificatore, dovresti copiare il comportamento e gli stili del blocco `link`. Ciò comporterà la duplicazione del codice. - Usa un mix del blocco universale `link` e l'elemento `item` del blocco `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>
Con la combinazione delle due entità BEM, ora puoi implementare la funzionalità di collegamento di base dal blocco `link` e regole CSS aggiuntive dal blocco `menu` ed evitare la duplicazione del codice.
Geometria esterna e posizionamento: rinunciare ai wrapper HTML astratti
I mix vengono utilizzati per posizionare un blocco rispetto ad altri blocchi o per posizionare elementi all'interno di un blocco. In BEM, gli stili responsabili della geometria e del posizionamento sono impostati nel blocco padre. Prendiamo un blocco di menu universale che deve essere posizionato nell'intestazione. Nel layout, il blocco deve avere un rientro di 20px dal blocco padre.
Questa attività ha diverse soluzioni:
- Scrivi stili con rientri per il blocco menu:
.menu { margin-left: 20px; }
In questo caso, il blocco "menu" non è più universale. Se devi posizionare il menu nel piè di pagina della pagina, dovrai modificare gli stili perché i rientri saranno probabilmente diversi. - Crea il modificatore di blocco 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; }
In questo caso, il progetto includerà due tipi di menu, anche se non è così. Il menu rimane lo stesso. - Definire il posizionamento esterno del blocco: annidare il blocco `menu` nel wrapper astratto (ad esempio il blocco `wrap`) impostando tutti i rientri:
<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>
Per evitare la tentazione di creare modificatori e modificare gli stili di blocco per posizionare il blocco sulla pagina, devi capire una cosa:Il rientro da un blocco padre non è una caratteristica del blocco nidificato. È una caratteristica del blocco padre. Deve sapere che il blocco annidato deve essere rientrato dal bordo di un certo numero di pixel.
- Usa un mix. Le informazioni sul posizionamento del blocco nidificato sono incluse negli elementi del blocco padre. Quindi l'elemento del blocco padre viene mescolato nel blocco nidificato. In questo caso, il blocco annidato non specifica alcun rientro e può essere facilmente riutilizzato in qualsiasi luogo.
Procediamo con il nostro esempio:
<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>
In questo caso, la geometria esterna e il posizionamento del blocco di menu
vengono impostati tramite l'elemento header__menu
. Il blocco menu
non specifica alcun rientro e può essere facilmente riutilizzato.
L'elemento di blocco padre (nel nostro caso è header__menu
) svolge il compito dei blocchi wrapper responsabili del posizionamento esterno del blocco.
Blocchi nella struttura del file
Tutti i progetti BEM hanno una struttura di file simile. La struttura dei file familiare semplifica agli sviluppatori la navigazione nel progetto, il passaggio da un progetto all'altro e lo spostamento di blocchi da un progetto all'altro.
L'implementazione di ogni blocco è memorizzata in una cartella di progetto separata. Ogni tecnologia (CSS, JavaScript, test, modelli, documentazione, immagini) si trova in un file separato.
Ad esempio, se l'aspetto del blocco di input
è impostato con CSS, il codice viene salvato nel file input.css
.
project common.blocks/ input/ input.css # The "input" block implementation with CSS input.js # The "input" block implementation with JavaScript
Il codice per modificatori ed elementi è anche memorizzato in file separati del blocco. Questo approccio consente di includere nella build solo i modificatori e gli elementi necessari per l'implementazione del blocco.
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
Per migliorare la navigazione del progetto, combinare i modificatori di blocco con più valori nelle directory.
La struttura dei file di qualsiasi progetto BEM consiste in livelli di ridefinizione (puoi saperne di più qui). I livelli di ridefinizione consentono di:
- Dividere il progetto in piattaforme;
- Aggiorna facilmente le librerie di blocchi incluse nel progetto;
- Utilizzare blocchi comuni per sviluppare più progetti;
- Modificare i temi progettuali senza intaccare la logica del progetto;
- Conduci esperimenti in un progetto dal vivo.
L'utilizzo dei blocchi e la memorizzazione di tutte le tecnologie dei blocchi nella stessa cartella semplificano lo spostamento dei blocchi tra i progetti. Per spostare tutti gli stili e il comportamento del blocco insieme al layout, basta copiare la cartella del blocco nel nuovo progetto.
Vantaggi non evidenti della metodologia
La convenienza dello sviluppo parallelo
In BEM, qualsiasi layout è diviso in blocchi. Poiché i blocchi sono indipendenti, possono essere sviluppati in parallelo da più sviluppatori.
Uno sviluppatore crea un blocco come componente universale che può essere riutilizzato in qualsiasi altro progetto.
Un esempio è la libreria di blocchi bem-components, che contiene blocchi universali, come un collegamento, un pulsante e un campo di input. È più facile creare blocchi più complessi da componenti universali. Ad esempio, un selettore o una casella di controllo.
L'utilizzo dei blocchi nel layout del progetto consente di risparmiare tempo nell'integrazione del codice scritto da diversi sviluppatori, garantisce l'unicità dei nomi dei componenti e consente di testare i blocchi nella fase di sviluppo.
Testare il layout
È problematico testare la funzionalità dell'intera pagina, soprattutto in un progetto dinamico connesso a un database.
In BEM, ogni blocco è coperto da test. I test sono una tecnologia di implementazione a blocchi, come Javascript o CSS. I blocchi vengono testati in fase di sviluppo. È più facile controllare la correttezza di un blocco e quindi assemblare il progetto da blocchi testati. Dopodiché, tutto ciò che devi fare è assicurarti che il wrapper di blocchi funzioni correttamente.
Costruzione personalizzabile di un progetto
Per uno sviluppo conveniente, tutti i blocchi e le tecnologie in un progetto BEM vengono inseriti in cartelle e file separati. Per combinare i file di origine in un unico file (ad esempio, per inserire tutti i file CSS in project.css
, tutti i file JS in project.js
e così via), utilizziamo il processo di compilazione.
La build esegue le seguenti attività:
- Combina i file di origine che sono sparsi nel file system del progetto;
- Include solo i blocchi, gli elementi e i modificatori necessari (entità BEM) nel progetto;
- Segue l'ordine di inclusione delle entità;
- Elabora il codice del file sorgente durante la compilazione (ad es. compila il codice LESS in codice CSS).
Per includere solo le entità BEM necessarie nella build, è necessario creare un elenco di blocchi, elementi e modificatori utilizzati nelle pagine. Questa lista è chiamata dichiarazione .
Poiché i blocchi BEM sono sviluppati indipendentemente e inseriti in file separati nel file system, non "sanno" nulla l'uno dell'altro. Per creare blocchi basati su altri blocchi, specifica le dipendenze. C'è una tecnologia BEM responsabile di questo: i file deps.js
I file di dipendenza consentono al motore di compilazione di sapere quali blocchi aggiuntivi devono essere inclusi nel progetto.
Caso pratico: BEM non è solo per CSS
Nelle sezioni precedenti, tutti gli esempi di codice sono per CSS. Ma BEM permette di modificare il comportamento del blocco e la sua rappresentazione in HTML nello stesso modo dichiarativo come nei CSS.
Come utilizzare la creazione di modelli in BEM
In HTML, il markup del blocco viene ripetuto ogni volta che il blocco viene visualizzato nella pagina. Se crei il markup HTML manualmente e poi devi correggere un errore o apportare modifiche, dovrai modificare il markup per ogni istanza del blocco. Per generare codice HTML e applicare correzioni automaticamente, BEM utilizza i modelli; i blocchi sono responsabili del modo in cui vengono presentati in HTML.
I modelli ti consentono di:
- Riduci il tempo impiegato per il debug del progetto, perché le modifiche al modello vengono applicate automaticamente a tutti i blocchi del progetto;
- Modificare il layout del blocco;
- Sposta i blocchi con il layout corrente in un altro progetto.
BEM utilizza il motore di modelli bem-xjst che presenta due motori:
- BEMHTML
Trasforma la descrizione BEMJSON della pagina in HTML. I modelli sono descritti nei file .bemhtml.js. - BEMTREE
Trasforma i dati in BEMJSON. I modelli sono descritti nel formato BEMJSON nei file .bemtree.js.
Se i modelli non vengono scritti per i blocchi, il motore dei modelli imposta il tag <div>
per i blocchi per impostazione predefinita.
Confronta la dichiarazione dei blocchi e l'output HTML:
Dichiarazione:
{ 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>
Per modificare il layout del blocco di menu
, è necessario scrivere dei modelli per il blocco:
- Cambiamo il tag del blocco
menu
:block('menu')( tag()('menu') // Set the "menu" tag for the menu block )
HTML modificato:<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>
Simile al CSS, il modello viene applicato a tutti i blocchi "menu" nella pagina. - Aggiungi un elemento aggiuntivo (
menu__inner
) che funziona come un wrapper interno ed è responsabile del layout degli elementi nel blocco dimenu
. Originariamente l'elementomenu__inner
non era incluso nella dichiarazione, quindi dobbiamo aggiungerlo quando i modelli vengono compilati.
I modelli BEM sono scritti in JavaScript, quindi puoi anche utilizzare JavaScript per aggiungere un nuovo elemento al modello: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>
- Sostituisci i tag per tutti gli elementi
inner
e degliitem
: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>
- Imposta il tag
<a>
per tutti i link nella pagina: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>
- Modifica il modello esistente. Le regole nei modelli vengono applicate allo stesso modo dei CSS: una regola inferiore ha la precedenza su una regola superiore. Aggiungi nuove regole al modello e modifica il tag link da
<a>
a<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 è un sistema personalizzabile
La metodologia BEM fornisce regole rigorose per creare un sistema nel tuo progetto. Ma allo stesso tempo, molte regole BEM possono essere personalizzate. La metodologia BEM consente di modificare la convenzione di denominazione, scegliere la struttura di file più conveniente o aggiungere al blocco le tecnologie desiderate.
Ora puoi sintonizzarti sul sistema e creare il tuo supereroe di BEM!
Come ottenere di più da BEM
Per iniziare ad apprendere i principi BEM, visita il nostro sito web. Se hai domande da porre al team, unisciti al nostro canale Telegram o apri una discussione nel nostro forum BEM.