Ereditarietà in SASS
Questo articolo spiega l'ereditarietà in SASS.
Spiegheremo l'ereditarietà in SASS con esempi pratici.
YouTube Video
Ereditarietà in SASS
L'ereditarietà in SASS (@extend) è un meccanismo che permette di applicare gli stili di un selettore ad un altro senza duplicazione. Poiché gli stessi stili vengono 'combinati' ed esportati per più elementi nel markup, il CSS risultante sarà meno ridondante; tuttavia, se usato in modo errato, può portare a fusioni indesiderate di selettori.
Basi: Come usare @extend
Di seguito un esempio base in cui .btn--primary eredita gli stili di .btn. @extend è una direttiva che estende il selettore di destinazione.
1// Base button styles
2.btn {
3 padding: 0.5rem 1rem;
4 border-radius: 4px;
5 border: 1px solid #ccc;
6 background: white;
7 color: #333;
8}
9
10/* Primary button extends the base .btn */
11.btn--primary {
12 @extend .btn;
13 background: #007bff;
14 color: white;
15}- Utilizzando
@extend,.btn--primaryeredita gli stili di base di.btne sovrascrive solo le parti necessarie.
CSS generato
1.btn, .btn--primary {
2 padding: 0.5rem 1rem;
3 border-radius: 4px;
4 border: 1px solid #ccc;
5 background: white;
6 color: #333;
7}
8
9.btn--primary {
10 background: #007bff;
11 color: white;
12}Best practice: utilizzo dei placeholder (%placeholder)
I selettori placeholder (%name) sono selettori che non vengono esportati in CSS. Sono ampiamente utilizzati soprattutto quando vuoi condividere in modo sicuro stili comuni esclusivamente per l’ereditarietà tra più componenti.
1// %placeholder will not be output directly
2%card-base {
3 padding: 1rem;
4 border-radius: 6px;
5 box-shadow: 0 1px 3px rgba(0,0,0,0.08);
6 background: #fff;
7}
8
9/* Components extend the placeholder */
10.card {
11 @extend %card-base;
12 border: 1px solid #eee;
13}
14
15.panel {
16 @extend %card-base;
17 border: 1px solid #ddd;
18}- Sia
.cardche.panelereditano da%card-base, permettendo loro di condividere gli stili comuni e aggiungere differenze dove necessario.
CSS generato
1.card, .panel {
2 padding: 1rem;
3 border-radius: 6px;
4 box-shadow: 0 1px 3px rgba(0,0,0,0.08);
5 background: #fff;
6}
7
8.card {
9 border: 1px solid #eee;
10}
11
12.panel {
13 border: 1px solid #ddd;
14}Ereditarietà multipla (più @extend)
È possibile ereditare più placeholder o classi contemporaneamente. Sebbene la riusabilità degli stili sia migliorata, è importante tenere traccia di quali regole sono combinate con quali selettori.
1%btn-base {
2 display: inline-block;
3 padding: 0.5rem 1rem;
4 border-radius: 3px;
5}
6
7%btn-large {
8 padding: 0.75rem 1.5rem;
9 font-size: 1.125rem;
10}
11
12/* Composite button that extends both placeholders */
13.btn--lg {
14 @extend %btn-base;
15 @extend %btn-large;
16 background: #222;
17 color: #fff;
18}- Questo è un esempio in cui un pulsante eredita due placeholder, uno per il 'base' e uno per le 'dimensioni'.
.btn--lgeredita sia%btn-baseche%btn-large, combinando il layout di base con una dimensione maggiore.
CSS generato
1.btn--lg {
2 display: inline-block;
3 /* %btn-large overrides the padding from %btn-base */
4 padding: 0.75rem 1.5rem;
5 border-radius: 3px;
6 font-size: 1.125rem;
7 background: #222;
8 color: #fff;
9}Comportamento di @extend (meccanismo di unione) e avvertenze sull'‘esplosione di selettori’
@extend esporta tutti i selettori corrispondenti uniti tra loro, il che a volte può portare a combinazioni indesiderate di selettori.
Il seguente esempio mostra come l'output possa aumentare quando la stessa classe base viene estesa in più punti.
1/* Many components extend .utility */
2/* A generic utility class */
3.utility {
4 margin-bottom: 1rem;
5}
6
7/* Nested selectors that extend .utility */
8.header {
9 @extend .utility;
10 .title {
11 font-weight: bold;
12 }
13}
14
15.footer {
16 @extend .utility;
17 .note {
18 color: #888;
19 }
20}
21
22.article {
23 @extend .utility;
24 .content {
25 line-height: 1.6;
26 }
27}
28
29.sidebar {
30 @extend .utility;
31 .section {
32 padding: 1rem;
33 }
34}- Quando più componenti ereditano
.utility, i selettori vengono uniti in uno solo e, nei progetti di grandi dimensioni, questo può far crescere il CSS.
CSS generato
1.utility,
2.header,
3.footer,
4.article,
5.sidebar {
6 margin-bottom: 1rem;
7}
8
9.header .title {
10 font-weight: bold;
11}
12
13.footer .note {
14 color: #888;
15}
16
17.article .content {
18 line-height: 1.6;
19}
20
21.sidebar .section {
22 padding: 1rem;
23}@extend e .class vs selettori di elemento (tag) — priorità ed effetti collaterali
@extend può essere applicato non solo alle classi ma anche ai selettori di elementi. Tuttavia, estendere elementi aumenta l’ambito interessato, aumentando il rischio che le regole vengano applicate inavvertitamente in luoghi non previsti.
Di seguito un esempio di estensione di un selettore di elemento e l'effetto che può avere.
1/* Extending an element selector (not recommended) */
2h1 {
3 font-size: 2rem;
4 margin-bottom: 0.5rem;
5}
6
7/* If you extend h1, the resulting selector will include your class with h1 */
8.title {
9 @extend h1;
10 color: #333;
11}
12
13/* Output becomes:
14h1, .title { font-size: 2rem; margin-bottom: 0.5rem; }
15*/- In questo esempio, ereditando il selettore di elemento
h1,.titleviene unito agli stessi stili dih1. - Anche se può sembrare conveniente in casi di piccola scala, man mano che il progetto cresce, le regole per
h1potrebbero combinarsi inaspettatamente con.title, rendendo gli stili più complessi e riducendo la manutenibilità. Pertanto, progettare gli stili principalmente attorno a classi e placeholder li rende più facili da mantenere.
CSS generato
1h1,
2.title {
3 font-size: 2rem;
4 margin-bottom: 0.5rem;
5}
6
7.title {
8 color: #333;
9}Casi d’uso per @extend e !optional
Se specifichi !optional con @extend, puoi sopprimere gli errori quando il target dell’ereditarietà non esiste. Questo è particolarmente utile in codice simile a una libreria o in casi in cui i placeholder sono definiti in modo condizionale.
Di seguito un esempio di tentativo sicuro di ereditare una classe che potrebbe non esistere, usando !optional.
1/* Try to extend a class that might not exist */
2.component {
3 @extend .maybe-existing !optional;
4 padding: 1rem;
5}- Se
.maybe-existingnon esiste, non succede nulla e viene ignorata. Puoi usare questa soluzione quando vuoi tentare un’estensione in modo sicuro.
CSS generato
1.component {
2 padding: 1rem;
3}Confronto tra @extend e mixin (@mixin / @include)
@extend e @mixin hanno talvolta scopi sovrapposti, ma i loro output e casi d'uso differiscono.
-
@extend- Il CSS generato riduce la ridondanza unendo i selettori.
- Poiché i selettori vengono uniti dopo la generazione, potrebbero verificarsi combinazioni indesiderate.
- Non è possibile passare parametri (anche se si può compensare combinando i placeholder).
-
@mixin/@include- Ogni chiamata duplica gli stili (causando output ridondante).
- È possibile passare parametri e includere logica come condizioni o cicli.
- L’output è più prevedibile, ma la dimensione del file aumenta.
Di seguito un confronto tra l'uso di @mixin e @extend per implementare gli stessi stili per i pulsanti.
1/* Mixin approach */
2@mixin btn-styles($bg, $color) {
3 display: inline-block;
4 padding: 0.5rem 1rem;
5 background: $bg;
6 color: $color;
7 border-radius: 4px;
8}
9
10/* Use mixin */
11.btn {
12 @include btn-styles(white, #333);
13}
14
15.btn--primary {
16 @include btn-styles(#007bff, white);
17}
18
19/* Extend approach (shared placeholder) */
20%btn-base {
21 display: inline-block;
22 padding: 0.5rem 1rem;
23 border-radius: 4px;
24}
25
26.btn2 {
27 @extend %btn-base;
28 background: white;
29 color: #333;
30}
31
32.btn2--primary {
33 @extend %btn-base;
34 background: #007bff;
35 color: white;
36}@mixinconsente di inserire gli stili in modo flessibile, mentre@extendconsolida l’output in modo efficiente, quindi puoi usarli come appropriato a seconda del caso d’uso.
CSS generato
Output da @mixin
1.btn {
2 display: inline-block;
3 padding: 0.5rem 1rem;
4 background: white;
5 color: #333;
6 border-radius: 4px;
7}
8
9.btn--primary {
10 display: inline-block;
11 padding: 0.5rem 1rem;
12 background: #007bff;
13 color: white;
14 border-radius: 4px;
15}Output da @extend
1.btn2,
2.btn2--primary {
3 display: inline-block;
4 padding: 0.5rem 1rem;
5 border-radius: 4px;
6}
7
8.btn2 {
9 background: white;
10 color: #333;
11}
12
13.btn2--primary {
14 background: #007bff;
15 color: white;
16}Linee guida pratiche
L’ereditarietà in SASS è una funzionalità potente per aumentare la riusabilità degli stili. Tuttavia, un uso scorretto può rendere la fusione degli stili complessa e ridurre la manutenibilità. Di seguito sono riportati alcuni punti chiave per utilizzare l’ereditarietà in modo sicuro ed efficiente.
- Usa i placeholder per stili puramente comuni dei componenti come struttura e layout. Inoltre, se è necessaria una parametrizzazione dinamica, puoi utilizzare
@mixin. - Dovresti evitare di ereditare direttamente elementi HTML come
h1. Potrebbero verificarsi combinazioni di selettori non previste, con il rischio che venga generato CSS inatteso. - L’utilizzo di convenzioni di denominazione come BEM o prefissi chiari per indicare lo scopo di ciascun placeholder aiuta a mantenere tutto più sicuro.
- È più sicuro utilizzare
@extendall’interno dello stesso file. Soprattutto nei progetti di grandi dimensioni, è consigliabile progettare l’ereditarietà nell’ambito di ciascun componente per facilitare il monitoraggio delle relazioni di ereditarietà.
Riepilogo
La funzione @extend in SASS è un modo pratico per riutilizzare in modo efficiente gli stili comuni e garantire la coerenza del design. Tuttavia, poiché le combinazioni di selettori possono facilmente diventare complesse, è necessario utilizzare questa funzione con attenzione e in un ambito limitato. Raggruppando gli stili condivisi con selettori placeholder (%placeholder) e utilizzando @mixin per le parti che richiedono parametri dinamici, puoi mantenere un design semplice e facilmente manutenibile.
Puoi seguire l'articolo sopra utilizzando Visual Studio Code sul nostro canale YouTube. Controlla anche il nostro canale YouTube.