Explorarea SMACSS: Arhitectură scalabilă și modulară pentru CSS
Publicat: 2022-03-11Când lucrăm la proiecte mari sau cu grupuri de dezvoltatori, descoperim adesea că codul nostru este dezordonat, greu de citit și greu de extins. Acest lucru este valabil mai ales după ce trece timpul și ne întoarcem și ne uităm la asta din nou - trebuie să încercăm să fim în aceeași mentalitate în care eram când am scris-o.
Deci, ceea ce au făcut mulți oameni este că au creat arhitecturi CSS pentru a ajuta la stilarea codului lor, astfel încât CSS să devină mai lizibil. SMACSS — adică, Arhitectura scalabilă și modulară pentru CSS — își propune să facă exact asta. Este un set special de reguli de arhitectură CSS de la Jonathan Snook pe care l-am adoptat.
Acum, abordarea arhitecturală a SMACSS este puțin diferită de un cadru CSS precum Bootstrap sau Foundation. În schimb, este un set de reguli, mai mult ca un șablon sau un ghid. Așa că haideți să ne aprofundăm câteva modele de design CSS pentru a afla cum le putem folosi pentru a face codul nostru mai bun, mai curat, mai ușor de citit și mai modular.
Fiecare structură de proiect SMACSS utilizează cinci categorii:
- Baza
- Aspect
- Module
- Stat
- Temă
Baza
În SMACSS, stilurile de bază definesc cum ar trebui să arate un element oriunde pe pagină. Sunt valorile implicite. Dacă utilizați o foaie de stil de resetare, aceasta vă asigură că stilurile rezultate sunt aceleași în toate browserele, în ciuda diferențelor dintre valorile implicite CSS de bază interne, codificate.
Într-un stil de bază, ar trebui să includeți numai selectoare de elemente goale sau cele cu pseudo-clase, dar nu cu selectoare de clasă sau ID. (Ar trebui să aveți motive foarte întemeiate să puneți clasă sau ID în el, poate numai dacă stilați elementele unui plugin terță parte și trebuie să înlocuiți stilul implicit pentru acel element anume.)
Iată un exemplu despre cum ar trebui să arate o unitate de fișiere de bază:
html { margin: 0; font-family: sans-serif; } a { color: #000; } button { color: #ababab; border: 1px solid #f2f2f2; }
Prin urmare, ar trebui să includă dimensiuni implicite, margini, culori, chenare și orice alte valori implicite pe care intenționați să le utilizați pe site-ul dvs. Tipografia și elementele de formular ar trebui să aibă stiluri unificate care să apară pe fiecare pagină și să ofere impresia și aspectul că fac parte din același design și temă.
SMACSS sau nu, recomand cu căldură să evitați utilizarea !important
pe cât posibil și să nu folosiți deep nesting, dar voi vorbi mai multe despre asta mai târziu în această postare. De asemenea, dacă practica dvs. este să utilizați resetare CSS, acesta este locul în care ar trebui să îl includeți. (Prefer să folosesc Sass, așa că îl includ doar în partea de sus a fișierului, mai degrabă decât să trebuiască să îl copiez sau să mă refer la el separat de elementul <head>
al fiecărei pagini.)
Aspect
Stilurile de aspect vor împărți pagina în secțiuni majore, nu secțiuni precum navigarea sau poate acordeonul, de exemplu, ci diviziuni de nivel superior:
Aceste aspecte vor conține mai multe module CSS, cum ar fi casete, carduri, liste neordonate, galerii și altele asemenea, dar voi vorbi mai multe despre module în secțiunea următoare. Să luăm în considerare un exemplu de pagină web pentru a vedea ce putem împărți în machete:
Aici avem antet, principal și subsol. Aceste layout-uri au module precum link-uri și logo în antetul din partea de sus, casete și articole pe principal și link-uri și drepturi de autor pentru subsol. De obicei oferim layout-urilor un selector de ID, deoarece acestea nu se repetă pe pagină și sunt unice.
De asemenea, ar trebui să prefixați regulile pentru stilurile de aspect cu litera l
pentru a le distinge de stilurile de modul. De obicei, aici ați stila lucruri specifice aspectului, cum ar fi chenarul, alinierea, marginile etc. De asemenea, fundalul acelei părți a paginii ar putea avea sens, chiar dacă nu pare să fie la fel de specific aspectului.
Iată un exemplu despre cum ar trebui să arate:
#header { background: #fcfcfc; } #header .l-right { float: right; } #header .l-align-center { text-align: center; }
De asemenea, puteți adăuga acești ajutoare pentru alinieri pe care le puteți utiliza pentru a poziționa cu ușurință elementele prin simpla adăugare a clasei corespunzătoare la copilul său sau pentru a-i alinia textul.
Pentru un alt exemplu, puteți utiliza unele margini implicite pe o casetă de aspect, cum ar fi .l-margin
care are o marjă de 20px
. Apoi, oriunde doriți umplutură pentru un container, element, card sau cutie, trebuie doar să adăugați clasa l-margin
la acesta. Dar vrei ceva reutilizabil:
.l-full-width { width: 100%; }
Nu ceva cuplat intern ca acesta:
.l-width-25 { width: 25px; }
Vreau să iau un moment pentru a vorbi despre convențiile de denumire în SMACSS. Dacă nu ați auzit niciodată de conceptul de spațiere a numelor în CSS, practic înseamnă adăugarea numelui la începutul unui alt element pentru a-l distinge de orice altceva. Dar de ce avem nevoie de asta?
Nu știu dacă ați întâlnit vreodată următoarea problemă. Scrieți CSS și aveți o etichetă pe ceva - puneți orice stiluri doriți și numiți clasa dvs. .label
. Dar apoi ajungeți la un alt element mai târziu și doriți să fie .label
, dar stilați-l diferit. Deci două lucruri diferite au același nume – un conflict de denumire.
Spațiul de nume vă ajută să rezolvați acest lucru. În cele din urmă, se numesc același lucru la un nivel, dar au un spațiu de nume diferit - un prefix diferit - și astfel pot reprezenta două stiluri diferite:
.box--label { color: blue; } .card--label { color: red; }
Modul
După cum am menționat mai devreme, modulele SMACSS sunt bucăți mai mici de cod care sunt reutilizabile pe pagină și fac parte dintr-un singur aspect. Acestea sunt părți ale CSS pe care dorim să le stocăm într-un folder separat, deoarece vom avea multe dintre acestea pe o singură pagină. Și pe măsură ce un proiect crește, putem împărți folosind cele mai bune practici privind structura de foldere, adică pe module/pagini:

Deci, în exemplul anterior, am avut un articol, care poate fi un modul în sine. Cum ar trebui să fie structurat CSS aici? Ar trebui să avem o clasă .article
care poate avea elemente copil title
și text
. Deci, pentru a-l putea păstra în același modul, trebuie să prefixăm elementele copil:
.article { background: #f32; } .article--title { font-size: 16px; } .article--text { font-size: 12px; }
Este posibil să observați că folosim două cratime după prefixul modulului. Motivul este că uneori numele modulelor au două cuvinte sau propriile lor prefixe, cum ar fi big-article
. Trebuie să avem două cratime pentru a spune ce parte din el este elementul copil - de exemplu, comparați big-article-title
big-article--title
și big-article--text
.
De asemenea, puteți imbrica module în interiorul modulelor dacă un anumit modul ocupă o mare parte a paginii:
<div class="box"> <div class="box--label">This is box label</div> <ul class="box--list list"> <li class="list--li">Box list element</li> </ul> </div>
Aici, în acest exemplu simplu, puteți vedea că box
este un modul și list
este un alt modul în interiorul acestuia. Deci list--li
este un copil al modulului list
și nu al box
. Unul dintre conceptele cheie aici este utilizarea maximă a doi selectoare pentru fiecare regulă CSS, dar în majoritatea scenariilor să aveți un singur selector cu prefixe.
Astfel, putem evita duplicarea regulilor și, de asemenea, să avem selectoare suplimentare pe elementele copil cu aceleași nume, îmbunătățind astfel viteza. Dar ne ajută și să evităm să folosim regulile nedorite de stil !important
, care sunt un semn al proiectelor CSS slab structurate.
Bun (rețineți selectorul unic):
.red--box { background: #fafcfe; } .red-box--list { color: #000; }
Proastă (rețineți repetiția în cadrul selectoarelor și metoda de referință suprapusă):
.red .box { background: #fafcfe; } .red .box .list { color: #000; } .box ul { color: #fafafa; }
Stat
Ceea ce starea definește în SMACSS este o modalitate de a descrie modul în care arată modulele noastre în diferite situații dinamice. Deci, această parte este într-adevăr pentru interactivitate: dorim un comportament diferit dacă un element este considerat a fi ascuns, extins sau modificat. De exemplu, un acordeon jQuery va avea nevoie de ajutor pentru a defini când puteți sau nu puteți vedea conținutul unui element. Ne ajută să definim stilul unui element la un moment dat.
Statele sunt aplicate aceluiași element ca aspectul, așa că adăugăm o regulă suplimentară care le va înlocui pe cele anterioare, dacă există. Regulii de stat i se acordă prioritate, deoarece este ultima din lanțul de reguli.
Ca și în cazul stilurilor de aspect, avem tendința de a folosi prefixe aici. Acest lucru ne ajută să le recunoaștem și să le acordăm prioritate. Aici folosim prefixul is
, ca în is-hidden
sau is-selected
.
<header> <ul class="nav"> <li class="nav--item is-selected">Contact</li> <li class="nav--item">About</li> </ul> </header>
.nav--item.is-selected { color: #fff; }
Aici, !important
poate fi folosit, deoarece starea este adesea folosită ca modificare JavaScript și nu în timpul randării. De exemplu, aveți un element care este ascuns la încărcarea paginii. Când faceți clic pe butonul, doriți să îl afișați. Dar clasa implicită este așa:
.box .element { display: none; }
Deci, dacă adaugi doar asta:
.is-shown { display: block; }
Va rămâne ascuns chiar și după ce adăugați clasa .is-shown
la element prin JavaScript. Acest lucru se datorează faptului că prima regulă are două niveluri adâncime și o va depăși.
Deci, puteți defini clasa de stare astfel:
.is-shown { display: block !important; }
Acesta este modul în care distingem modificatorii de stare de cei de aspect, care se aplică numai la încărcarea inițială a unei pagini. Acest lucru va funcționa acum, păstrând avantajele selectoarelor minime.
Temă
Acesta ar trebui să fie cel mai evident, deoarece este folosit pentru a conține regulile culorilor primare, forme, margini, umbre și altele. În cea mai mare parte, acestea sunt elemente care se repetă pe întregul site. Nu vrem să le redefinim de fiecare dată când le creăm. În schimb, dorim să definim o clasă unică pe care o adăugăm mai târziu la un element implicit.
.button-large { width: 60px; height: 60px; }
<button class="button-large">Like</button>
Nu confunda aceste reguli de teme SMACSS cu cele de bază, deoarece regulile de bază vizează doar aspectul implicit și tind să fie ceva asemănător cu resetarea la setările implicite ale browserului, în timp ce o unitate temă este mai mult un tip de stil în care oferă aspectul final, unic pentru această schemă specifică de culori.
Regulile de teme pot fi, de asemenea, utile dacă un site are mai mult de un singur stil sau poate câteva teme utilizate în state diferite și, prin urmare, pot fi schimbate sau schimbate cu ușurință în timpul unor evenimente de pe o pagină, de exemplu, cu un buton de comutare a temei. Cel puțin, păstrează toate stilurile de teme într-un singur loc, astfel încât să le puteți schimba cu ușurință și să le păstrați frumos organizate.
Metodologii de organizare CSS
Am acoperit câteva dintre conceptele cheie ale acestei idei de arhitectură CSS. Dacă doriți să aflați mai multe despre acest concept, puteți vizita site-ul oficial al SMACSS și puteți aprofunda în el.
Da, probabil că puteți utiliza metodologii mai avansate precum OOCSS și BEM. Acesta din urmă acoperă aproape întregul flux de lucru frontend și tehnologiile sale. Selectoarele BEM pot funcționa grozav pentru unii oameni, dar unii le pot considera prea lungi și copleșitori și, de asemenea, prea complicat de utilizat. Dacă aveți nevoie de ceva mai simplu, care este mai ușor de preluat și de încorporat în fluxul dvs. de lucru – și, de asemenea, de ceva care să definească regulile de bază pentru dvs. și pentru echipa dvs. – SMACSS se potrivește perfect.
Va fi ușor pentru noii membri ai echipei nu numai să înțeleagă ce au făcut dezvoltatorii anteriori, ci și să înceapă să lucreze la asta instantaneu, fără diferențe în stilul de codare. SMACSS este doar o arhitectură CSS și face ceea ce scrie pe tablă - nimic mai mult și nimic mai puțin.