Proprietăți personalizate CSS în cascadă

Publicat: 2022-03-10
Rezumat rapid ↬ În acest articol, Miriam aprofundează în specificația „Proprietăți personalizate CSS pentru variabile în cascadă” pentru a se întreba: „De ce sunt numite proprietăți personalizate, cum funcționează în cascadă și ce altceva putem face cu ele ?” Depășind metafora „variabilă”, proprietățile personalizate pot oferi noi modalități de a echilibra contextul și izolarea în modelele și componentele CSS.

Luna trecută, am avut o conversație pe Twitter despre diferența dintre stilurile „limitate” (generate într-un proces de construire) și stilurile „imbricate” native pentru CSS. Am întrebat de ce, în mod anecdotic, dezvoltatorii evită specificul selectoarelor de ID, în timp ce îmbrățișează „stilurile de acoperire” generate de JavaScript? Keith Grant a sugerat că diferența constă în echilibrarea cascadei* și moștenirea, adică acordarea de preferință proximității față de specificitate. Hai să aruncăm o privire.

Cascada

Cascada CSS se bazează pe trei factori:

  1. Importanța definită de semnul !important și originea stilului (utilizator > autor > browser)
  2. Specificitatea selectoarelor utilizate (inline > ID > class > element)
  3. Ordinea sursă a codului în sine (cel mai recent are prioritate)

Proximitatea nu este menționată nicăieri - relația DOM-arborele dintre părțile unui selector. Paragrafele de mai jos vor fi ambele roșii, chiar dacă #inner p descrie o relație mai strânsă decât #outer p pentru al doilea paragraf:

Vedeți Pen [Cascade: Specificity vs Proximity](https://codepen.io/smashingmag/pen/OexweJ/) de Miriam Suzanne.

Vezi Cascada Pen: Specificitate vs Proximitate de Miriam Suzanne.
 <section> <p>This text is red</p> <div> <p>This text is also red!</p> </div> </section>
 #inner p { color: green; } #outer p { color: red; }

Ambii selectori au aceeași specificitate, ambii descriu același element p și niciunul nu este marcat ca !important - deci rezultatul se bazează numai pe ordinea sursei.

Mai multe după săritură! Continuați să citiți mai jos ↓

BEM și stiluri Scoped

Convențiile de denumire cum ar fi BEM („Block__Element—Modifier”) sunt folosite pentru a se asigura că fiecare paragraf este „acoperit” doar unui părinte, evitând în întregime cascada. Paragrafele „elemente” primesc clase unice specifice contextului lor de „bloc”:

Vezi stiloul [BEM Selectors & Proximity](https://codepen.io/smashingmag/pen/qzPyeM/) de Miriam Suzanne.

Vedeți Pen BEM Selectors & Proximity de Miriam Suzanne.
 <section class="outer"> <p class="outer__p">This text is red</p> <div class="inner"> <p class="inner__p">This text is green!</p> </div> </section>
 .inner__p { color: green; } .outer__p { color: red; }

Acești selectori au încă aceeași importanță relativă, specificitate și ordinea surselor - dar rezultatele sunt diferite. Instrumentele CSS „acoperite” sau „modulare” automatizează acest proces, rescriind CSS-ul nostru pentru noi, pe baza HTML. În codul de mai jos, fiecare paragraf este limitat la părintele său direct:

Vedeți Pen [Scoped Style Proximity](https://codepen.io/smashingmag/pen/NZaLWN/) de Miriam Suzanne.

Vedeți Pen Scoped Style Proximity de Miriam Suzanne.
 <section outer-scope> <p outer-scope>This text is red</p> <div outer-scope inner-scope> <p inner-scope>This text is green!</p> </div> </section>
 p[inner-scope] { color: green } p[outer-scope] { color: red; }

Moştenire

Proximitatea nu face parte din cascadă, dar face parte din CSS. Acolo devine importantă moștenirea . Dacă aruncăm p din selectoarele noștri, fiecare paragraf va moșteni o culoare de la cel mai apropiat strămoș:

Vezi stiloul [Moștenire: specificitate vs proximitate](https://codepen.io/smashingmag/pen/mZBGyN/) de Miriam Suzanne.

Vezi Moștenirea stiloului: specificitate vs proximitate de Miriam Suzanne.
 #inner { color: green; } #outer { color: red; }

Deoarece #inner și #outer descriu elemente diferite, respectiv div -ul și respectiv section noastră, ambele proprietăți de culoare sunt aplicate fără conflict. Elementul p imbricat nu are nicio culoare specificată, astfel încât rezultatele sunt determinate de moștenire (culoarea părintelui direct) mai degrabă decât de cascadă . Proximitatea are prioritate, iar valoarea #inner suprascrie pe #outer .

Dar există o problemă: pentru a folosi moștenirea, stilăm totul în section noastră și div . Dorim să vizam în mod specific culoarea paragrafului.

(Re-)introducerea proprietăților personalizate

Proprietățile personalizate oferă o soluție nouă, nativă pentru browser; moștenesc ca orice altă proprietate, dar nu trebuie să fie folosite acolo unde sunt definite . Folosind CSS simplu, fără convenții de denumire sau instrumente de construcție, putem crea un stil care este atât direcționat, cât și contextual, cu proximitatea având prioritate față de cascadă:

Vezi stiloul [Custom Props: Specificity vs Proximity](https://codepen.io/smashingmag/pen/gNGdaO/) de Miriam Suzanne.

Vedeți Recunoașterea personalizată a stiloului: specificitate vs proximitate de Miriam Suzanne.
 p { color: var(--paragraph); } #inner { --paragraph: green; } #outer { --paragraph: red; }

Proprietatea personalizată --paragraph moștenește la fel ca proprietatea color , dar acum avem control asupra modului exact și unde este aplicată acea valoare. Proprietatea --paragraph acționează similar cu un parametru care poate fi trecut în componenta p , fie prin selecție directă (specificitate-reguli) fie prin context (proximitate-reguli).

Cred că acest lucru dezvăluie un potențial pentru proprietăți personalizate pe care adesea le asociem cu funcții, mixuri sau componente.

„Funcții” și parametri personalizați

Funcțiile, mixurile și componentele se bazează pe aceeași idee: cod reutilizabil, care poate fi rulat cu diferiți parametri de intrare pentru a obține rezultate consistente, dar configurabile. Distincția constă în ceea ce fac ei cu rezultatele. Vom începe cu o variabilă cu gradient în dungi și apoi o putem extinde în alte forme:

 html { --stripes: linear-gradient( to right, powderblue 20%, pink 20% 40%, white 40% 60%, pink 60% 80%, powderblue 80% ); }

Acea variabilă este definită pe elementul html rădăcină (ar putea folosi și :root , dar asta adaugă specificitate inutilă), astfel încât variabila noastră cu dungi va fi disponibilă peste tot în document. O putem aplica oriunde sunt acceptate gradienti:

Vezi stiloul [Custom Props: Variable](https://codepen.io/smashingmag/pen/NZwrrm/) de Miriam Suzanne.

Vedeți Piesa personalizată Props: Variable de Miriam Suzanne.
 body { background-image: var(--stripes); }

Adăugarea parametrilor

Funcțiile sunt folosite ca variabile, dar definesc parametrii pentru modificarea ieșirii. Putem actualiza variabila noastră --stripes pentru a fi mai asemănătoare cu funcțiile prin definirea unor variabile asemănătoare parametrilor în interiorul acesteia. Voi începe prin a înlocui to right cu var(--stripes-angle) , pentru a crea un parametru de schimbare a unghiului:

 html { --stripes: linear-gradient( var(--stripes-angle), powderblue 20%, pink 20% 40%, white 40% 60%, pink 60% 80%, powderblue 80% ); }

Există și alți parametri pe care i-am putea crea, în funcție de scopul pentru care este menită să servească funcția. Ar trebui să le permitem utilizatorilor să aleagă propriile culori de dungi? Dacă da, funcția noastră acceptă 5 parametri de culoare diferiți sau doar 3 care vor merge afară-înăuntru așa cum avem acum? Dorim să creăm parametri și pentru opriri de culoare? Fiecare parametru pe care îl adăugăm oferă mai multă personalizare cu prețul simplității și consecvenței.

Nu există un răspuns corect universal la acest echilibru - unele funcții trebuie să fie mai flexibile, iar altele trebuie să fie mai obișnuite. Abstracțiile există pentru a oferi consistență și lizibilitate în codul dvs., așa că faceți un pas înapoi și întrebați care sunt obiectivele dvs. Ce trebuie să fie cu adevărat personalizabil și unde ar trebui să fie impusă consecvența? În unele cazuri, ar putea fi mai util să aveți două funcții cu opinii, mai degrabă decât o funcție complet personalizabilă.

Pentru a folosi funcția de mai sus, trebuie să transmitem o valoare pentru parametrul --stripes-angle și să aplicăm rezultatul unei proprietăți de ieșire CSS, cum ar fi background-image :

 /* in addition to the code above… */ html { --stripes-angle: 75deg; background-image: var(--stripes); } 

Vezi stiloul [Custom Props: Function](https://codepen.io/smashingmag/pen/BgwOjj/) de Miriam Suzanne.

Vezi Pix Personalizat Props: Function de Miriam Suzanne.

Moștenit versus universal

Am definit funcția --stripes pe elementul html din obișnuință. Proprietățile personalizate moștenesc și vreau ca funcția mea să fie disponibilă peste tot, așa că are sens să o pun pe elementul rădăcină. Acest lucru funcționează bine pentru moștenirea variabilelor precum --brand-color: blue , așa că ne-am putea aștepta să funcționeze și pentru „funcția” noastră. Dar dacă încercăm să folosim din nou această funcție pe un selector imbricat, nu va funcționa:

Vezi stiloul [Custom Props: Function Inheritance Fail](https://codepen.io/smashingmag/pen/RzjRrM/) de Miriam Suzanne.

Vedeți Recunoașterea personalizată a stiloului: eșec de moștenire a funcției de Miriam Suzanne.
 div { --stripes-angle: 90deg; background-image: var(--stripes); }

Noul --stripes-angle este ignorat în întregime. Se pare că nu ne putem baza pe moștenire pentru funcțiile care trebuie recalculate. Acest lucru se datorează faptului că fiecare valoare de proprietate este calculată o dată pe element (în cazul nostru, elementul rădăcină html ), iar apoi valoarea calculată este moștenită . Prin definirea funcției noastre la rădăcina documentului, nu punem întreaga funcție disponibilă descendenților, ci doar rezultatul calculat al funcției noastre.

Acest lucru are sens dacă îl încadrați în ceea ce privește parametrul cascading --stripes-angle . Ca orice proprietate CSS moștenită, este disponibilă pentru descendenți, dar nu pentru strămoși. Valoarea pe care o setăm pe un div imbricat nu este disponibilă pentru o funcție pe care am definit-o pe strămoșul rădăcină html . Pentru a crea o funcție disponibilă universal care va recalcula pe orice element, trebuie să o definim pe fiecare element:

Vezi stiloul [Custom Props: Universal Function](https://codepen.io/smashingmag/pen/agLaNj/) de Miriam Suzanne.

Vezi Pix Personalizat Props: Universal Function de Miriam Suzanne.
 * { --stripes: linear-gradient( var(--stripes-angle), powderblue 20%, pink 20% 40%, white 40% 60%, pink 60% 80%, powderblue 80% ); }

Selectorul universal face ca funcția noastră să fie disponibilă peste tot, dar o putem defini mai restrâns dacă dorim. Important este că poate recalcula doar acolo unde este definit în mod explicit. Iată câteva alternative:

 /* make the function available to elements with a given selector */ .stripes { --stripes: /* etc… */; } /* make the function available to elements nested inside a given selector */ .stripes * { --stripes: /* etc… */; } /* make the function available to siblings following a given selector */ .stripes ~ * { --stripes: /* etc… */; } 

Vezi stiloul [Custom Props: Scoped Function](https://codepen.io/smashingmag/pen/JQMvGM/) de Miriam Suzanne.

Vedeți Recuzită personalizată pentru stilou: Funcție cu scop de Miriam Suzanne.

Acest lucru poate fi extins cu orice logică de selecție care nu se bazează pe moștenire.

Parametri liberi și valori de rezervă

În exemplul nostru de mai sus, var(--stripes-angle) nu are nicio valoare și nicio rezervă. Spre deosebire de variabilele Sass sau JS care trebuie definite sau instanțiate înainte de a fi apelate, proprietățile personalizate CSS pot fi apelate fără a fi definite vreodată. Aceasta creează o variabilă „liberă”, similară unui parametru de funcție care poate fi moștenit din context.

În cele din urmă, putem defini variabila pe html sau :root (sau orice alt strămoș) pentru a seta o valoare moștenită, dar mai întâi trebuie să luăm în considerare alternativa dacă nu este definită nicio valoare. Există mai multe opțiuni, în funcție de exact ce comportament ne dorim

  1. Pentru parametrii „obligatori”, nu dorim o rezervă. Așa cum este, funcția nu va face nimic până când --stripes-angle este definit.
  2. Pentru parametrii „opționali”, putem furniza o valoare de rezervă în funcția var() . După numele-variabilă, adăugăm o virgulă, urmată de valoarea implicită:
 var(--stripes-angle, 90deg)

Fiecare funcție var() poate avea doar o singură alternativă - astfel încât orice virgulă suplimentară va face parte din acea valoare. Acest lucru face posibilă furnizarea de valori implicite complexe cu virgule interne:

 html { /* Computed: Hevetica, Ariel, sans-serif */ font-family: var(--sans-family, Hevetica, Ariel, sans-serif); /* Computed: 0 -1px 0 white, 0 1px 0 black */ test-shadow: var(--shadow, 0 -1px 0 white, 0 1px 0 black); }

De asemenea, putem folosi variabile imbricate pentru a crea propriile reguli în cascadă, dând diferite priorități diferitelor valori:

 var(--stripes-angle, var(--global-default-angle, 90deg))
  1. Mai întâi, încercați parametrul nostru explicit ( --stripes-angle );
  2. Revenire la un „user default” global ( --user-default-angle ) dacă este disponibil;
  3. În cele din urmă, reveniți la „prestabilit din fabrică” (90deg ).

Vezi stiloul [Custom Props: Fallback Values](https://codepen.io/smashingmag/pen/jjGvVm/) de Miriam Suzanne.

Vedeți Piesa personalizată a creionului: Valori de rezervă de Miriam Suzanne.

Prin setarea valorilor de rezervă în var() în loc să definim proprietatea personalizată în mod explicit, ne asigurăm că nu există restricții specifice sau în cascadă asupra parametrului. Toți parametrii *-angle sunt „liberi” pentru a fi moșteniți din orice context.

Fallback-uri browser versus alternative variabile

Când folosim variabile, există două căi de rezervă de care trebuie să ținem cont:

  1. Ce valoare ar trebui să fie folosită de browserele fără suport pentru variabile?
  2. Ce valoare ar trebui să fie utilizată de browserele care acceptă variabile, atunci când o anumită variabilă lipsește sau este invalidă?
 p { color: blue; color: var(--paragraph); }

În timp ce browserele vechi vor ignora proprietatea declarației variabilelor și vor reveni la blue , browserele moderne le vor citi pe ambele și le vor folosi pe cea din urmă. var(--paragraph) poate să nu fie definit, dar este valid și va suprascrie proprietatea anterioară, astfel încât browserele cu suport pentru variabile vor reveni la valoarea moștenită sau inițială, ca și cum ar folosi cuvântul cheie unset .

Poate părea confuz la început, dar există motive întemeiate pentru asta. Prima este tehnică: motoarele de browser gestionează sintaxa invalidă sau necunoscută la „timp de analiză” (ceea ce se întâmplă mai întâi), dar variabilele nu sunt rezolvate până la „timpul valorii calculate” (ceea ce se întâmplă mai târziu).

  1. La momentul analizei, declarațiile cu sintaxă nevalidă sunt ignorate complet - recurgând la declarațiile anterioare. Aceasta este calea pe care o vor urma browserele vechi. Browserele moderne acceptă sintaxa variabilă, astfel încât declarația anterioară este eliminată.
  2. La momentul valorii calculate, variabila este compilată ca nevalidă, dar este prea târziu - declarația anterioară a fost deja eliminată. Conform specificațiilor, valorile variabilelor invalide sunt tratate la fel ca unset :

Vezi stiloul [Custom Props: Invalid/Unsupported vs Undefined](https://codepen.io/smashingmag/pen/VJMGbJ/) de Miriam Suzanne.

Consultați Elementele personalizate pentru stilou: Invalid/Neacceptat vs Nedefinit de Miriam Suzanne.
 html { color: red; /* ignored as *invalid syntax* by all browsers */ /* - old browsers: red */ /* - new browsers: red */ color: not a valid color; color: var(not a valid variable name); /* ignored as *invalid syntax* by browsers without var support */ /* valid syntax, but invalid *values* in modern browsers */ /* - old browsers: red */ /* - new browsers: unset (black) */ --invalid-value: not a valid color value; color: var(--undefined-variable); color: var(--invalid-value); }

Acest lucru este bun și pentru noi, ca autori, deoarece ne permite să ne jucăm cu alternative mai complexe pentru browserele care acceptă variabile și să furnizăm soluții simple pentru browserele mai vechi. Și mai bine, asta ne permite să folosim starea null / undefined pentru a seta parametrii necesari. Acest lucru devine deosebit de important dacă dorim să transformăm o funcție într-un mixin sau componentă.

Proprietate personalizată „Mixins”

În Sass, funcțiile returnează valori brute, în timp ce mixurile returnează, în general, ieșirea CSS reală cu perechi proprietate-valoare. Când definim o proprietate universală --stripes , fără a o aplica la nicio ieșire vizuală, rezultatul este asemănător unei funcții. Putem face ca acesta să se comporte mai mult ca un mixin, definind și ieșirea universal:

 * { --stripes: linear-gradient( var(--stripes-angle), powderblue 20%, pink 20% 40%, white 40% 60%, pink 60% 80%, powderblue 80% ); background-image: var(--stripes); }

Atâta timp cât --stripes-angle rămâne invalid sau nedefinit, mixin-ul nu reușește să se compileze și nu se va aplica nicio background-image . Dacă setăm un unghi valid pentru orice element, funcția va calcula și ne va oferi un fundal:

 div { --stripes-angle: 30deg; /* generates the background */ }

Din păcate, acel parametru-valoare va moșteni, așa că definiția curentă creează un fundal pe div și toți descendenții . Pentru a remedia acest lucru, trebuie să ne asigurăm că valoarea --stripes-angle nu moștenește, adăugându-l la initial (sau la orice valoare invalidă) pe fiecare element. Putem face asta pe același selector universal:

Vezi stiloul [Custom Props: Mixin](https://codepen.io/smashingmag/pen/ZdXMJx/) de Miriam Suzanne.

Vezi elementele personalizate pentru stilou: Mixin de Miriam Suzanne.
 * { --stripes-angle: initial; --stripes: /* etc… */; background-image: var(--stripes); }

Stiluri sigure în linie

În unele cazuri, avem nevoie ca parametrul să fie setat dinamic din afara CSS - pe baza datelor de la un server back-end sau un cadru front-end. Cu proprietăți personalizate, putem defini în siguranță variabile în HTML-ul nostru, fără a ne îngrijora de problemele obișnuite de specificitate:

Vezi stiloul [Custom Props: Mixin + Inline Style](https://codepen.io/smashingmag/pen/qzPMPv/) de Miriam Suzanne.

Vezi Elementele personalizate pentru stilou: Mixin + Stil în linie de Miriam Suzanne.
 <div>...</div>

Stilurile inline au o specificitate ridicată și sunt foarte greu de anulat - dar cu proprietăți personalizate, avem o altă opțiune: ignorați-o. Dacă setăm div-ul la background-image: none (de exemplu), acea variabilă inline nu va avea niciun impact. Pentru a o duce și mai departe, putem crea o variabilă intermediară:

 * { --stripes-angle: var(--stripes-angle-dynamic, initial); }

Acum avem opțiunea de a defini --stripes-angle-dynamic în HTML, sau de a-l ignora și de a seta --stripes-angle direct în foaia noastră de stil.

Vezi stiloul [Custom Props: Mixin + Inline / Override](https://codepen.io/smashingmag/pen/ZdXMao/) de Miriam Suzanne.

Vezi elementele personalizate pentru stilou: Mixin + Inline / Override de Miriam Suzanne.

Valori prestabilite

Pentru valori mai complexe sau modele comune pe care dorim să le reutilizam, putem oferi și câteva variabile prestabilite din care să alegem:

 * { --tilt-down: 6deg; --tilt-up: -6deg; }

Și folosiți acele presetări, în loc să setați valoarea direct:

 <div>...</div> 

Vezi stiloul [Custom Props: Mixin + Presets](https://codepen.io/smashingmag/pen/LKemZm/) de Miriam Suzanne.

Vezi elementele personalizate pentru stilou: Mixin + Presets de Miriam Suzanne.

Acest lucru este excelent pentru a crea diagrame și grafice bazate pe date dinamice sau chiar pentru a crea un planificator de zi.

Vedeți Pen [Diagrama cu bare în grila CSS + variabile](https://codepen.io/smashingmag/pen/wLrEyg/) de Miriam Suzanne.

Vedeți graficul Pen Bar în grila CSS + variabile de Miriam Suzanne.

Componente contextuale

De asemenea, putem reîncadra „mixinul” nostru ca „componentă” aplicând-o la un selector explicit și făcând parametrii opționali. În loc să ne bazăm pe prezența sau absența --stripes-angle pentru a comuta ieșirea, ne putem baza pe prezența sau absența unui selector de componente. Acest lucru ne permite să setăm valorile de rezervă în siguranță:

Vezi stiloul [Custom Props: Component](https://codepen.io/smashingmag/pen/QXqVmM/) de Miriam Suzanne.

Vezi pixul personalizat Props: Component de Miriam Suzanne.
 [data-stripes] { --stripes: linear-gradient( var(--stripes-angle, to right), powderblue 20%, pink 20% 40%, white 40% 60%, pink 60% 80%, powderblue 80% ); background-image: var(--stripes); }

Prin introducerea de rezervă în interiorul funcției var() , putem lăsa --stripes-angle nedefinit și „liber” pentru a moșteni o valoare din afara componentei. Aceasta este o modalitate excelentă de a expune anumite aspecte ale unui stil component la intrarea contextuală. Chiar și stilurile „limitate” generate de un cadru JS (sau acoperite în interiorul shadow-DOM, cum ar fi pictogramele SVG) pot folosi această abordare pentru a expune parametrii specifici pentru influența externă.

Componente izolate

Dacă nu dorim să expunem parametrul pentru moștenire, putem defini variabila cu o valoare implicită:

 [data-stripes] { --stripes-angle: to right; --stripes: linear-gradient( var(--stripes-angle, to right), powderblue 20%, pink 20% 40%, white 40% 60%, pink 60% 80%, powderblue 80% ); background-image: var(--stripes); }

Aceste componente ar funcționa și cu o clasă sau cu orice alt selector valid, dar am ales atributul data- pentru a crea un spațiu de nume pentru orice modificatori pe care îi dorim:

 [data-stripes='vertical'] { --stripes-angle: to bottom; } [data-stripes='horizontal'] { --stripes-angle: to right; } [data-stripes='corners'] { --stripes-angle: to bottom right; } 

Vezi stiloul [Custom Props: Isolated Components](https://codepen.io/smashingmag/pen/agLaGX/) de Miriam Suzanne.

Vezi pixul personalizat Props: Isolated Components de Miriam Suzanne.

Selectoare și parametri

Adesea mi-aș dori să pot folosi atributele de date pentru a seta o variabilă - o caracteristică acceptată de specificația CSS3 attr() , dar care nu este încă implementată în niciun browser (consultați fila de resurse pentru problemele legate de fiecare browser). Acest lucru ne-ar permite să asociem mai strâns un selector cu un anumit parametru:

 <div data-stripes="30deg">...</div> /* Part of the CSS3 spec, but not yet supported */ /* attr( , ) */ [data-stripes] { --stripes-angle: attr(data-stripes angle, to right); } <div data-stripes="30deg">...</div> /* Part of the CSS3 spec, but not yet supported */ /* attr( , ) */ [data-stripes] { --stripes-angle: attr(data-stripes angle, to right); } <div data-stripes="30deg">...</div> /* Part of the CSS3 spec, but not yet supported */ /* attr( , ) */ [data-stripes] { --stripes-angle: attr(data-stripes angle, to right); }

Între timp, putem realiza ceva similar utilizând atributul style :

Vezi stiloul [Custom Props: Style Selectors](https://codepen.io/smashingmag/pen/PrJdBG/) de Miriam Suzanne.

Vezi Elementele personalizate pentru stilou: selectoare de stil de Miriam Suzanne.
 <div>...</div> /* The `*=` atttribute selector will match a string anywhere in the attribute */ [style*='--stripes-angle'] { /* Only define the function where we want to call it */ --stripes: linear-gradient(…); }

Această abordare este cea mai utilă atunci când dorim să includem și alte proprietăți în plus față de parametrul care este setat. De exemplu, setarea unei zone de grilă ar putea adăuga, de asemenea, umplutură și fundal:

 [style*='--grid-area'] { background-color: white; grid-area: var(--grid-area, auto / 1 / auto / -1); padding: 1em; }

Concluzie

Când începem să punem toate aceste piese împreună, devine clar că proprietățile personalizate depășesc cu mult cazurile de utilizare variabile comune cu care suntem familiarizați. Nu doar că suntem capabili să stocăm valori și să le întindem în cascadă, dar le putem folosi pentru a manipula cascada în moduri noi și pentru a crea componente mai inteligente direct în CSS.

Acest lucru ne cere să regândim multe dintre instrumentele pe care ne-am bazat în trecut - de la convențiile de denumire precum SMACSS și BEM, până la stiluri „cu domeniu” și CSS-in-JS. Multe dintre aceste instrumente ajută la rezolvarea specificității sau la gestionarea stilurilor dinamice într-o altă limbă - cazuri de utilizare pe care acum le putem aborda direct cu proprietăți personalizate. Stilurile dinamice pe care le-am calculat adesea în JS, pot fi acum gestionate prin transmiterea datelor brute în CSS.

La început, aceste modificări pot fi văzute ca „complexitate adăugată” – deoarece nu suntem obișnuiți să vedem logica în interiorul CSS. Și, ca în cazul oricărui cod, suprainginerirea poate fi un pericol real. Dar aș susține că, în multe cazuri, putem folosi această putere nu pentru a adăuga complexitate, ci pentru a muta complexitatea din instrumentele și convențiile terților, înapoi în limbajul de bază al designului web și (mai important) înapoi în browser. Dacă stilurile noastre necesită calcul, acel calcul ar trebui să trăiască în CSS-ul nostru.

Toate aceste idei pot fi duse mult mai departe. Proprietățile personalizate abia încep să aibă o adoptare mai largă și abia am început să zgâriem suprafața a ceea ce este posibil. Sunt încântat să văd unde se duce asta și cu ce mai vin oamenii. A se distra!

Lectură suplimentară

  • „Este timpul să începem să utilizați proprietăți personalizate CSS”, Serg Hospodarets
  • „Un ghid de strategie pentru proprietăți personalizate CSS”, Michael Riethmuller