BEM pentru începători: de ce aveți nevoie de BEM

Publicat: 2022-03-10
Rezumat rapid ↬ Izolarea stilurilor CSS este cel mai frecvent punct de pornire al utilizării BEM. Dar acesta este cel puțin pe care BEM ți-l poate oferi. BEM aduce o abordare de sistem în proiectul dvs. și îl ține de mizerie.

BEM face codul dvs. scalabil și reutilizabil, crescând astfel productivitatea și facilitând munca în echipă. Chiar dacă ești singurul membru al echipei, BEM îți poate fi de folos. Cu toate acestea, mulți dezvoltatori cred că o astfel de abordare de sistem, cum ar fi BEM, pune limite suplimentare proiectului lor și face ca proiectul să fie supraîncărcat, greoi și lent.

Vom colecta toate aspectele principale ale BEM într-o formă condensată. Acest articol vă ajută să înțelegeți ideile de bază ale BEM în doar 20 de minute și să respingeți prejudecățile conform cărora abordarea de sistem este dăunătoare proiectului dumneavoastră.

Big BEM constă din Metodologie , Tehnologii , Biblioteci și Instrumente . În acest articol, vom vorbi mai mult despre metodologia în sine, deoarece este experiența concentrată a unui număr mare de dezvoltatori și aduce o abordare sistematică oricărui proiect.

Pentru a vă arăta câteva cazuri practice de BEM, vom aborda tehnologiile BEM și vom omite complet bibliotecile și instrumentele.

De la teorie la practică:

  • Principalele motive pentru care nu folosim niciun selector, cu excepția claselor
  • Bazele BEM
    • Blocuri și elemente
    • Modificatori și amestecuri
    • Blocuri în structura fișierului
  • Avantajele neevidente ale metodologiei
  • Caz practic: BEM nu este doar pentru CSS
  • BEM este un sistem personalizabil

Deci, este BEM un erou sau un răufăcător? Depinde de tine! Dar mai întâi, citește articolul.

BEM ca sigla Batman
BEMBatman
Mai multe după săritură! Continuați să citiți mai jos ↓

Principalele motive pentru care nu folosim niciun selector, cu excepția claselor

Una dintre regulile de bază ale metodologiei BEM este utilizarea doar selectoare de clasă. În această secțiune, vom explica de ce.

  • De ce nu folosim ID-uri?
  • De ce nu folosim selectoare de etichete?
  • De ce nu folosim un selector universal?
  • De ce nu folosim resetarea CSS?
  • De ce nu folosim selectoare imbricate?
  • De ce nu combinăm o etichetă și o clasă într-un selector?
  • De ce nu folosim selectoare combinate-
  • De ce nu folosim selectori de atribute?

Nu folosim ID-uri (selectoare ID)

ID-ul oferă un nume unic pentru un element HTML. Dacă numele este unic, nu îl puteți reutiliza în interfață. Acest lucru vă împiedică să reutilizați codul.

Concepții greșite comune

  1. ID-urile sunt necesare pentru utilizarea JavaScript.
    Browserele moderne pot funcționa fie cu ID-uri, fie cu clase. Orice tip de selector este procesat în același ritm în browser.
  2. ID-urile sunt folosite cu <label> .
    Dacă plasați <label> în interiorul unui control, acesta nu are nevoie de un ID. În loc de <input id="ID"><label for="ID">Text</label> , utilizați pur și simplu <label><input type="...">Text</label> .

Nu folosim selectoare de etichete

Marcarea paginii HTML este instabilă: un design nou poate schimba imbricarea secțiunilor, nivelurile de titlu (de exemplu, de la <h1> la <h3> ) sau poate transforma paragraful <p> în eticheta <div> . Oricare dintre aceste modificări va rupe stilurile care sunt scrise pentru etichete. Chiar dacă designul nu se schimbă, setul de etichete este limitat. Pentru a utiliza un aspect existent într-un alt proiect, trebuie să rezolvați conflictele dintre stilurile scrise pentru aceleași etichete.

Nici un set extins de etichete semantice nu poate satisface toate nevoile de aspect.

Un exemplu este atunci când antetul paginii conține o siglă. Un clic pe siglă deschide pagina principală a site-ului ( index ). Îl puteți marca cu etichete folosind eticheta <img> pentru imagine și eticheta <a> pentru link.

 <header> <a href="/"> <img src="img.logo.png" alt="Logo"> </a> </header>

Pentru a distinge între link-ul logo-ului și un link obișnuit din text, aveți nevoie de stiluri suplimentare. Acum eliminați sublinierea și culoarea albastră de pe link-ul logo-ului:

 header a { ... }

Nu este necesar ca linkul pentru logo să fie afișat pe pagina principală, așa că modificați marcajul paginii de index:

 <header> <!-- the <a> tag is replaced with <span> --> <span> <img src="img.logo.png" alt="Logo"> </span> </header>

Nu trebuie să eliminați sublinierea și culoarea albastră pentru eticheta <span> . Deci, să facem reguli generale pentru link-ul logo-ului din diferite pagini:

 header a, header span { ... }

La prima vedere, acest cod pare în regulă, dar imaginați-vă dacă designerul elimină sigla din aspect. Numele selectorului nu vă ajută să înțelegeți ce stiluri ar trebui eliminate din proiectul cu sigla. Selectorul „antet a” nu arată legătura dintre link și logo. Acest selector ar putea aparține linkului din meniul antet sau, de exemplu, linkului către profilul autorului. Selectorul „interval antet” poate aparține oricărei părți a antetului.

Pentru a evita confuzia, utilizați selectorul clasei logo pentru a scrie stilurile de logo:

 .logo { ... }

Nu folosim CSS Resetare

Resetarea CSS este un set de reguli CSS globale create pentru întreaga pagină. Aceste stiluri afectează toate nodurile de aspect, încalcă independența componentelor și îngreunează reutilizarea acestora.

În BEM, „resetare” și „normalizare” nici măcar nu sunt folosite pentru un singur bloc. Resetarea și normalizarea anulează stilurile existente și înlocuiește-le cu alte stiluri, pe care va trebui să le modificați și să le actualizați ulterior, în orice caz. Ca rezultat, dezvoltatorul trebuie să scrie stiluri care le înlocuiesc pe cele care tocmai au fost resetate.

Nu folosim selectorul universal ( * )

Selectorul universal indică faptul că proiectul prezintă un stil care afectează toate nodurile din aspect. Acest lucru limitează reutilizarea aspectului în alte proiecte:

  • În plus, trebuie să transferați stilurile cu un asterisc în proiect. Dar în acest caz, selectorul universal ar putea afecta stilurile din noul proiect.
  • Stilurile cu un asterisc trebuie adăugate la aspectul pe care îl transferați.

În plus, un selector universal poate face codul de proiect imprevizibil. De exemplu, poate afecta stilurile componentelor bibliotecii universale.

Stilurile comune nu vă economisesc timp. Adesea, dezvoltatorii încep prin a reseta toate marjele pentru componente ( * { margin: 0; padding: 0; } ), dar apoi le setează în continuare la fel ca în aspect (de exemplu, margin: 12px; padding: 30px; ).

Nu folosim selectoare imbricate

Selectoarele imbricate măresc cuplarea codului și fac dificilă reutilizarea codului.

Metodologia BEM nu interzice selectoare imbricate, dar recomandă să nu le folosiți prea mult. De exemplu, imbricarea este potrivită dacă trebuie să schimbați stilurile elementelor în funcție de starea blocului sau de tema atribuită acestuia.

 .button_hovered .button__text { text-decoration: underline; } .button_theme_islands .button__text { line-height: 1.5; }

Nu folosim selectoare combinate

Selectoarele combinate sunt mai specifice decât selectoarele unice, ceea ce face mai dificilă redefinirea blocurilor.

Luați în considerare următorul cod:

 <button class="button button_theme_islands">...</button>

Să presupunem că setați reguli CSS în selectorul .button.button_theme_islands pentru a scrie mai puțin. Apoi adăugați modificatorul „activ” la bloc:

 <button class="button button_theme_islands button_active">...</button>

Selectorul .button_active nu redefinește proprietățile blocului scrise ca .button.button_theme_islands deoarece .button.button_theme_islands este mai specific decât .button_active . Pentru a-l redefini, combinați selectorul modificator de bloc cu selectorul .button și declarați-l sub .button.button_theme_islands , deoarece ambii selectori sunt la fel de specifici:

 .button.button_theme_islands {} .button.button_active {}

Dacă utilizați selectoare simple de clasă, nu veți avea probleme la redefinirea stilurilor:

 .button_theme_islands {} .button_active {} .button {}

Nu combinăm o etichetă și o clasă într-un selector

Combinarea unei etichete și a unei clase în același selector (de exemplu, button.button ) face regulile CSS mai specifice, deci este mai dificil să le redefiniți.

Luați în considerare următorul cod:

 <button class="button">...</button>

Să presupunem că setați reguli CSS în selectorul button.button . Apoi adăugați modificatorul active la bloc:

 <button class="button button_active">...</button>

Selectorul .button_active nu redefinește proprietățile blocului scrise ca button.button deoarece button.button este mai specific decât .button_active . Pentru a-l face mai specific, ar trebui să combinați selectorul modificator de bloc cu eticheta button.button_active .

Pe măsură ce proiectul se dezvoltă, s-ar putea să ajungeți cu blocuri cu input.button , span.button sau a.button . În acest caz, toți modificatorii blocului button și toate elementele sale imbricate vor necesita patru declarații diferite pentru fiecare instanță.

Posibile excepții

În cazuri rare, metodologia permite combinarea selectoarelor de etichete și clase. De exemplu, aceasta poate fi folosită pentru setarea stilului de comentarii în sistemele CMS care nu pot genera aspectul corect.

Puteți folosi comentariul pentru a scrie un text, a insera imagini sau a adăuga markup. Pentru a le face să se potrivească cu designul site-ului, dezvoltatorul poate predefini stiluri pentru toate etichetele disponibile utilizatorului și le poate transfera în cascadă în blocurile imbricate:

 <div class="content"> ... <!-- the user's text --> </div> CSS rules: .content a { ... } .content p { font-family: Arial, sans-serif; text-align: center; }

Nu folosim selectori de atribute

Selectorii de atribute sunt mai puțin informative decât selectorii de clasă. Ca dovadă, luați în considerare un exemplu cu un formular de căutare în antet:

 <header> <form action="/"> <input name="s"> <input type="submit"> </form> </header>

Încercați să utilizați atributele selectorului pentru a scrie stilurile de formular:

 header input[type=submit], header input[type=checkbox] { width: auto; margin-right: 20px; } header input[type=checkbox] { margin: 0; }

În acest exemplu, nu puteți spune cu siguranță din numele selectorului că stilurile aparțin formularului de căutare. Folosirea claselor face totul mai clar. Cursurile nu au restricții care să vă împiedice să scrieți clar. De exemplu, puteți scrie astfel:

 .form .search { ... }

Acum codul este mai puțin ambiguu și este clar că stilurile aparțin formularului de căutare.

Dar selectoarele imbricate fac în continuare regulile CSS mai specifice și vă împiedică să transferați aspectul între proiecte. Pentru a scăpa de cuibărire, utilizați principiile BEM.

Rezumat : class este singurul selector care vă permite să izolați stilurile fiecărei componente din proiect; crește lizibilitatea codului și nu limitează reutilizarea aspectului.

Izolarea stilurilor CSS este cel mai frecvent punct de plecare al călătoriei BEM. Dar acesta este cel puțin pe care BEM ți-l poate oferi. Pentru a înțelege modul în care componentele independente izolate sunt aranjate în BEM, trebuie să învățați conceptele de bază, adică Bloc, Element, Modificator și Mix. Să facem asta în secțiunea următoare.

Bazele BEM

  • Blocuri și elemente
  • Modificatori și amestecuri
  • Blocuri în structura fișierului

Bloc și elemente

Metodologia BEM este un set de reguli universale care pot fi aplicate indiferent de tehnologiile folosite, precum CSS, Sass, HTML, JavaScript sau React.

BEM ajută la rezolvarea următoarelor sarcini:

  • Reutilizați aspectul;
  • Mutați fragmente de aspect într-un proiect în siguranță;
  • Mutați aspectul final între proiecte;
  • Creați cod stabil, previzibil și clar;
  • Reduceți timpul de depanare a proiectului.

Într-un proiect BEM, interfața constă din blocuri care pot include elemente. Blocurile sunt componente independente ale paginii. Un element nu poate exista în afara blocului, așa că rețineți că fiecare element poate aparține unui singur bloc.

Primele două litere din BEM reprezintă încuietori B și elemente E. Numele blocului este întotdeauna unic. Setează spațiul de nume pentru elemente și oferă o conexiune vizibilă între părțile blocului. Numele blocurilor sunt lungi, dar clare, pentru a arăta conexiunea dintre componente și pentru a evita pierderea oricăror părți a acestor componente la transferul aspectului.

Pentru a vedea întreaga putere a denumirii BEM, luați în considerare acest exemplu cu un formular. Conform metodologiei BEM, formularul este implementat folosind blocul form . În HTML, numele blocului este inclus în atributul class :

 <form class="form" action="/">

Toate părțile formei (blocul de form ) care nu au sens în sine sunt considerate elemente ale acesteia. Deci caseta de căutare ( search ) și butonul ( submit ) sunt elemente ale blocului form . Clasele indică, de asemenea, că un element aparține blocului:

 <form class="form" action="/"> <input class="form__search" name="s"> <input class="form__submit" type="submit"> </form>

Rețineți că numele blocului este separat de numele elementului cu un separator special. În schema clasică de denumire BEM, două litere de subliniere sunt folosite ca separator. Orice poate funcționa ca separator. Există convenții alternative de denumire și fiecare dezvoltator o alege pe cea care li se potrivește. Important este că separatoarele vă permit să distingeți blocurile de elemente și modificatori în mod programatic.

Numele selectorului arată clar că, pentru a muta formularul într-un alt proiect, trebuie să copiați toate componentele acestuia:

 .form__search {} .form__submit {}

Folosirea blocurilor și elementelor pentru numele claselor rezolvă o problemă importantă: ne ajută să scăpăm de selectoarele imbricate. Toți selectorii dintr-un proiect BEM au aceeași pondere. Asta înseamnă că este mult mai ușor să redefiniți stilurile scrise conform BEM. Acum, pentru a utiliza același formular într-un alt proiect, puteți doar să copiați aspectul și stilurile acestuia.

Ideea denumirii componentelor BEM este că puteți defini în mod explicit conexiunea dintre bloc și elementele sale.

Modificatori și amestecuri

Oficial, „M” înseamnă M odifier, dar implică și o noțiune mai importantă în BEM: „mix”. Atât modificatorii, cât și amestecurile fac modificări unui bloc și elementelor acestuia. Să aruncăm o privire mai atentă la asta.

Modificatori

Un modificator definește aspectul, starea și comportamentul unui bloc sau al unui element. Adăugarea modificatorilor este opțională. Modificatorii vă permit să combinați diferite funcții de bloc, deoarece puteți utiliza orice număr de modificatori. Dar unui bloc sau unui element nu i se pot atribui valori diferite ale aceluiași modificator.

Să explorăm cum funcționează modificatorii.

Imaginați-vă că proiectul are nevoie de același formular de căutare ca în exemplul de mai sus. Ar trebui să aibă aceleași funcții, dar să arate diferit (de exemplu, formularele de căutare din antet și din subsolul paginii ar trebui să difere). Primul lucru pe care îl puteți face pentru a schimba aspectul formularului este să scrieți stiluri suplimentare:

 header .form {} footer .form {}

header .form selector are mai multă greutate decât selectorul de form , ceea ce înseamnă că o regulă o va înlocui pe cealaltă. Dar, după cum am discutat, selectoarele imbricate măresc cuplarea codului și fac reutilizarea dificilă, așa că această abordare nu funcționează pentru noi.

În BEM, puteți folosi un modificator pentru a adăuga noi stiluri la bloc:

 <!-- 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>

Linia <form class="form form_type_original"></form> indică faptul că blocului i s-a atribuit un modificator de type cu valoarea original . Într-o schemă clasică, numele modificatorului este separat de numele blocului sau al elementului cu un caracter de subliniere.

Formularul poate avea o temă unică de culoare, dimensiune, tip sau design. Toți acești parametri pot fi setați cu un modificator:

 <form class="form form_type_original form_size_m form_theme_forest"> <form class="form form_type_original form_size_m form_theme_forest">

Aceeași formă poate arăta diferit, dar rămâne la aceeași dimensiune:

 <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>

Dar selectoarele pentru fiecare modificator vor avea în continuare aceeași pondere:

 .form_type_original {} .form_size_m {} .form_theme_forest {}

Important : Un modificator conține doar stiluri suplimentare care modifică într-un fel implementarea blocului original. Acest lucru vă permite să setați aspectul unui bloc universal o singură dată și să adăugați numai acele caracteristici care diferă de codul original al blocului în stilurile modificatoare.

 .form { /* universal block styles */ } .form_type_original { /* added styles */ }

Acesta este motivul pentru care un modificator ar trebui să fie întotdeauna pe același nod DOM cu blocul și elementul cu care este asociat.

 <form class="form form_type_original"></form>

Puteți folosi modificatori pentru a aplica componente universale în cazuri foarte specifice. Codul blocului și al elementului nu se modifică. Combinația necesară de modificatori este creată pe nodul DOM.

Amestecuri

O combinație vă permite să aplicați aceeași formatare la diferite elemente HTML și să combinați comportamentul și stilurile mai multor entități, evitând în același timp duplicarea codului. Ele pot înlocui blocurile de înveliș abstracte.

Un mix înseamnă că găzduiești mai multe entități BEM (blocuri, elemente, modificatori) pe un singur nod DOM. Similar modificatorilor, amestecurile sunt folosite pentru schimbarea blocurilor. Să ne uităm la câteva exemple de când ar trebui să utilizați un amestec.

Blocurile pot diferi nu numai vizual, ci și semantic. De exemplu, un formular de căutare, un formular de înregistrare și un formular de comandă de prăjituri sunt toate forme. În layout, acestea sunt implementate cu blocul „form”, dar nu au niciun stil în comun. Este imposibil să gestionezi astfel de diferențe cu un modificator. Puteți defini stiluri comune pentru astfel de blocuri, dar nu veți putea reutiliza codul.

 .form, .search, .register { ... }

Puteți folosi o combinație pentru a crea blocuri semantic diferite pentru aceeași formă:

 <form class="form" action="/"> <input class="form__search" name="s"> <input class="form__submit" type="submit"> </form>

Selectorul clasei .form descrie toate stilurile care pot fi aplicate oricărui formular (comandă, căutare sau înregistrare):

 .form {}

Acum puteți face un formular de căutare din formularul universal. Pentru a face acest lucru, creați o clasă de search suplimentară în proiect. Această clasă va fi responsabilă numai de căutare. Pentru a combina stilurile și comportamentul claselor .form și .search , plasați aceste clase pe un singur nod DOM:

 <form class="form search" action="/"> <input class="form__search" name="s"> <input class="form__submit" type="submit"> </form>

În acest caz, clasa .search este un bloc separat care definește comportamentul. Acest bloc nu poate avea modificatori responsabili pentru formă, teme și dimensiuni. Acești modificatori aparțin deja formei universale. Un amestec ajută la combinarea stilurilor și comportamentului acestor blocuri.

Să luăm încă un exemplu în care semantica componentei este schimbată. Iată un meniu de navigare în antetul paginii în care toate intrările sunt link-uri:

 <nav class="menu"> <a class="link" href=""></a> <a class="link" href=""></a> <a class="link" href=""></a> </nav>

Funcționalitatea de link este deja implementată în blocul de link , dar linkurile de meniu trebuie să difere vizual de linkurile din text. Există mai multe moduri de a schimba link-urile meniului:

  1. Creați un modificator de intrare în meniu care transformă intrarea într-un 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>

    În acest caz, pentru a implementa modificatorul, ar trebui să copiați comportamentul și stilurile blocului `link`. Acest lucru va duce la duplicarea codului.
  2. Utilizați o combinație de bloc universal „link” și elementul „articol” din blocul „meniu”:
     <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>

    Cu combinația celor două entități BEM, acum puteți implementa funcționalitatea de bază a link-ului din blocul `link` și regulile CSS suplimentare din blocul `menu` și puteți evita duplicarea codului.

Geometrie și poziționare externă: renunțarea la învelișurile HTML abstracte

Mixurile sunt folosite pentru a poziționa un bloc în raport cu alte blocuri sau pentru a poziționa elemente în interiorul unui bloc. În BEM, stilurile responsabile pentru geometrie și poziționare sunt setate în blocul părinte. Să luăm un bloc de meniu universal care trebuie plasat în antet. În aspect, blocul trebuie să aibă o indentare de 20px față de blocul părinte.

Această sarcină are mai multe soluții:

  1. Scrieți stiluri cu indentări pentru blocul de meniu:
     .menu { margin-left: 20px; }

    În acest caz, blocul „meniu” nu mai este universal. Dacă trebuie să plasați meniul în subsolul paginii, va trebui să editați stiluri pentru că probabil că indenturile vor fi diferite.
  2. Creați modificatorul blocului de meniu:
     <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; }

    În acest caz, proiectul va include două tipuri de meniuri, deși nu este cazul. Meniul rămâne același.
  3. Definiți poziționarea externă a blocului: imbricați blocul `menu` în wrapper-ul abstract (de exemplu, blocul `wrap`) setând toate indentările:
     <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>

    Pentru a evita tentația de a crea modificatori și de a schimba stilurile de bloc pentru a poziționa blocul pe pagină, trebuie să înțelegeți un lucru:

    Indentarea dintr-un bloc părinte nu este o caracteristică a blocului imbricat. Este o caracteristică a blocului părinte. Trebuie să știe că blocul imbricat trebuie să fie indentat de la margine cu un anumit număr de pixeli.
  4. Utilizați un amestec. Informațiile despre poziționarea blocurilor imbricate sunt incluse în elementele blocului părinte. Apoi elementul bloc părinte este amestecat în blocul imbricat. În acest caz, blocul imbricat nu specifică nicio indentare și poate fi reutilizat cu ușurință în orice loc.

Să continuăm cu exemplul nostru:

 <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>

În acest caz, geometria externă și poziționarea blocului de menu sunt stabilite prin elementul header__menu . Blocul de menu nu specifică nicio liniuță și poate fi reutilizat cu ușurință.

Elementul bloc părinte (în cazul nostru este header__menu ) îndeplinește sarcina blocurilor wrapper responsabile de poziționarea externă a blocului.

Blocuri în structura fișierului

Toate proiectele BEM au o structură de fișiere similară. Structura familiară de fișiere facilitează pentru dezvoltatori navigarea în proiect, comutarea între proiecte și mutarea blocurilor de la un proiect la altul.

Implementarea fiecărui bloc este stocată într-un folder separat de proiect. Fiecare tehnologie (CSS, JavaScript, teste, șabloane, documentație, imagini) se află într-un fișier separat.

De exemplu, dacă aspectul blocului de input este setat cu CSS, codul este salvat în fișierul input.css .

 project common.blocks/ input/ input.css # The "input" block implementation with CSS input.js # The "input" block implementation with JavaScript

Codul pentru modificatori și elemente este, de asemenea, stocat în fișiere separate ale blocului. Această abordare vă permite să includeți în build doar acei modificatori și elemente care sunt necesare pentru implementarea blocului.

 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

Pentru a îmbunătăți navigarea în proiect, combinați modificatorii de bloc cu mai multe valori în directoare.

Structura de fișiere a oricărui proiect BEM constă din niveluri de redefinire (puteți afla mai multe despre ele aici). Nivelurile de redefinire vă permit să:

  • Împărțiți proiectul în platforme;
  • Actualizați cu ușurință bibliotecile de bloc incluse în proiect;
  • Utilizați blocuri comune pentru a dezvolta mai multe proiecte;
  • Schimbați temele de design fără a afecta logica proiectului;
  • Efectuați experimente într-un proiect live.

Utilizarea blocurilor și stocarea tuturor tehnologiilor de blocare în același folder facilitează mutarea blocurilor între proiecte. Pentru a muta toate stilurile și comportamentul blocului împreună cu aspectul, copiați folderul bloc în noul proiect.

Avantajele neevidente ale metodologiei

Comoditatea dezvoltării paralele

În BEM, orice aspect este împărțit în blocuri. Deoarece blocurile sunt independente, pot fi dezvoltate în paralel de mai mulți dezvoltatori.

Un dezvoltator creează un bloc ca componentă universală care poate fi reutilizată în orice alt proiect.

Un exemplu este biblioteca de blocuri bem-components, care conține blocuri universale, cum ar fi un link, un buton și un câmp de intrare. Este mai ușor să creați blocuri mai complexe din componente universale. De exemplu, un selector sau o casetă de selectare.

Utilizarea blocurilor în aspectul proiectului vă ajută să economisiți timp la integrarea codului scris de mai mulți dezvoltatori, garantează unicitatea numelor componentelor și vă permite să testați blocurile în etapa de dezvoltare.

Testarea aspectului

Este problematic să testați funcționalitatea întregii pagini, mai ales într-un proiect dinamic conectat la o bază de date.

În BEM, fiecare bloc este acoperit de teste. Testele sunt o tehnologie de implementare în bloc, cum ar fi Javascript sau CSS. Blocurile sunt testate în stadiul de dezvoltare. Este mai ușor să verificați corectitudinea unui bloc și apoi să asamblați proiectul din blocurile testate. După aceea, tot ce trebuie să faceți este să vă asigurați că învelișul bloc funcționează corect.

Crearea personalizabilă a unui proiect

Pentru o dezvoltare convenabilă, toate blocurile și tehnologiile dintr-un proiect BEM sunt plasate în foldere și fișiere separate. Pentru a combina fișierele sursă într-un singur fișier (de exemplu, pentru a pune toate fișierele CSS în project.css , toate fișierele JS în project.js și așa mai departe), folosim procesul de compilare.

Build-ul îndeplinește următoarele sarcini:

  • Combină fișierele sursă care sunt răspândite în sistemul de fișiere al proiectului;
  • Include doar blocurile, elementele și modificatorii necesari (entități BEM) în proiect;
  • Urmează ordinea de includere a entităților;
  • Procesează codul fișierului sursă în timpul construcției (de exemplu, compilează LESS cod în cod CSS).

Pentru a include numai entitățile BEM necesare în build, trebuie să creați o listă de blocuri, elemente și modificatori utilizați în pagini. Această listă se numește declarație .

Deoarece blocurile BEM sunt dezvoltate independent și plasate în fișiere separate în sistemul de fișiere, ele nu „știu” nimic unul despre celălalt. Pentru a construi blocuri bazate pe alte blocuri, specificați dependențele. Există o tehnologie BEM responsabilă pentru aceasta: fișierele deps.js Fișierele de dependență indică motorului de compilare ce blocuri suplimentare trebuie incluse în proiect.

Caz practic: BEM nu este doar pentru CSS

În secțiunile anterioare, toate exemplele de cod sunt pentru CSS. Dar BEM vă permite să modificați comportamentul blocului și reprezentarea acestuia în HTML în același mod declarativ ca și în CSS.

Cum să utilizați șablonul în BEM

În HTML, marcarea blocurilor se repetă de fiecare dată când blocul apare pe pagină. Dacă creați manual marcajul HTML și apoi trebuie să remediați o eroare sau să faceți modificări, va trebui să modificați marcajul pentru fiecare instanță a blocului. Pentru a genera cod HTML și a aplica remedieri automat, BEM folosește șabloane; blocurile sunt responsabile pentru modul în care sunt prezentate în HTML.

Șabloanele vă permit să:

  • Reduceți timpul folosit pentru depanarea proiectului, deoarece modificările șablonului sunt aplicate automat tuturor blocurilor de proiect;
  • Modificați aspectul blocului;
  • Mutați blocurile cu aspectul curent într-un alt proiect.

BEM folosește motorul de șablon bem-xjst care include două motoare:

  • BEMHTML
    Transformă descrierea BEMJSON a paginii în HTML. Șabloanele sunt descrise în fișiere .bemhtml.js.
  • BEMTREE
    Transformă datele în BEMJSON. Șabloanele sunt descrise în format BEMJSON în fișiere .bemtree.js .

Dacă șabloanele nu sunt scrise pentru blocuri, motorul de șabloane setează implicit eticheta <div> pentru blocuri.

Comparați declarația blocurilor și rezultatul HTML:

Declaraţie:

 { 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>

Pentru a modifica aspectul blocului de menu , trebuie să scrieți șabloane pentru bloc:

  1. Să schimbăm eticheta blocului de menu :
     block('menu')( tag()('menu') // Set the "menu" tag for the menu block )

    HTML modificat:
     <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>

    Similar cu CSS, șablonul este aplicat tuturor blocurilor „meniu” din pagină.
  2. Adăugați un element suplimentar ( menu__inner ) care funcționează ca un înveliș interior și este responsabil pentru aspectul elementelor din blocul de menu . Inițial, elementul menu__inner nu a fost inclus în declarație, așa că trebuie să îl adăugăm atunci când șabloanele sunt construite.

    Șabloanele BEM sunt scrise în JavaScript, așa că puteți utiliza și JavaScript pentru a adăuga un nou element la șablon:
     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>
  3. Înlocuiți etichetele pentru toate elementele inner și ale item :
     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>
  4. Setați eticheta <a> pentru toate linkurile de pe pagină:
     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>
  5. Modificați șablonul existent. Regulile din șabloane sunt aplicate în același mod ca și în CSS: o regulă inferioară înlocuiește o regulă mai mare. Adăugați reguli noi la șablon și schimbați eticheta de link din <a> în <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 este un sistem personalizabil

Metodologia BEM vă oferă reguli stricte pentru a crea un sistem în proiectul dumneavoastră. Dar, în același timp, o mulțime de reguli BEM pot fi personalizate. Metodologia BEM vă permite să schimbați convenția de denumire, să alegeți cea mai convenabilă structură de fișiere sau să adăugați orice tehnologii dorite la bloc.

Acum puteți să vă conectați la sistem și să vă creați propriul super-erou din BEM!

BEM ca sigla Captain America
BEM Căpitanul America

Cum să obțineți mai mult de la BEM

Pentru a începe să învățați principiile BEM, vizitați site-ul nostru web. Dacă aveți întrebări pe care doriți să le adresați echipei, alăturați-vă canalului nostru Telegram sau deschideți o discuție în Forumul nostru BEM.