Corso di CSS / Variabili CSS: var(), ambito, ereditarietà e valori di ripiego

Le proprietà personalizzate CSS memorizzano valori riutilizzabili e sono richiamate con var() nei valori delle proprietà. Il loro ambito segue la cascata e l'ereditarietà, e un valore di riserva var() non recupera automaticamente un valore definito che non è valido per la proprietà ricevente.

Scegli variabili condivise significative

Se usi lo stesso colore di accento per più pulsanti e schede, puoi raggrupparlo in una variabile significativa invece di copiare il codice colore in ogni selettore. Modificando la dichiarazione condivisa, aggiorni tutti i punti che la richiamano. Creare variabili anche per valori usati una sola volta e privi di un ruolo riconoscibile può invece rendere più difficile seguire il foglio di stile.

:root {
  --accent: #1d5f91;
  --space-unit: .5rem;
}
.button { color: white; background: var(--accent); }
.card { border: 2px solid var(--accent); padding: calc(var(--space-unit) * 3); }

Dichiarare semplicemente un colore nel codice sopra non cambia l’aspetto della pagina. Le proprietà effettive, come background o border, devono richiamare la variabile con var(). Se il nome indica il ruolo, come --accent, piuttosto che fissare il colore attuale, come --blue, sarà meno confuso quando si cambierà in un colore diverso più tardi. --accent e --Accent sono nomi diversi, quindi rispetta maiuscole, minuscole e ortografia.

var() viene usato per il valore di proprietà come color o padding. I selettori o i nomi delle proprietà non possono essere sostituiti con variabili, e non puoi usare var() per definire un breakpoint nelle condizioni di @media (min-width: ...) o di una query sulla dimensione del contenitore: var() non è ammesso in queste condizioni. Scrivi i breakpoint direttamente nella corrispondente istruzione condizionale e distinguili dai valori ai quali possono essere applicate variabili, come il colore o lo spazio degli elementi.

Comprendere root, ereditarietà e ambito dei componenti

In un documento HTML, :root corrisponde all'elemento HTML di livello superiore, quindi è comodo avere un valore predefinito comune nel documento. Le proprietà personalizzate non registrate, con nomi che iniziano con --, vengono ereditate dai discendenti. La registrazione con @property può invece definire tipo, valore iniziale e comportamento di ereditarietà; gli esempi qui usano proprietà non registrate. I valori dichiarati all'interno di una scheda possono essere utilizzati dai discendenti, come il titolo, ma non vengono trasmessi a schede sorelle non correlate.

.card { --card-accent: var(--accent); }
.card.warning { --card-accent: #a63e32; }
.card { border-color: var(--card-accent); }
.card h2 { color: var(--card-accent); }

Questa regola fa parte del componente dell'esempio completo qui sotto. .card.warning corrisponde alle schede con entrambe le classi. L’ordine delle classi nell’attributo HTML non decide quale dichiarazione prevale: il valore dipende dalle regole di ereditarietà, specificità e cascata CSS. Cambiare l'accento globale cambierà la scheda predefinita, e le schede di avviso con il proprio --card-accent manterranno i loro colori di avviso originali.

Quando si combinano variabili con altre variabili, è anche importante da quale elemento viene calcolato il valore. Se --line-color: var(--accent) viene calcolato nel genitore e poi passato al figlio, il colore della linea già ereditato non viene ricalcolato solo perché l'accento viene sovrascritto nel figlio. I valori derivati che dovrebbero seguire l'accento dei loro discendenti vanno dichiarati nell’elemento interessato, oppure sostituiti con un riferimento diretto all’accento nella proprietà che lo utilizza. Per definizioni di ambito ed ereditarietà, vedere specifica CSS delle proprietà personalizzate.

Distinguere tra fallback e valori calcolati non validi

var(--notice-color, #6a3989) fornisce un valore di fallback viola quando il valore di una variabile manca e non può essere utilizzato. Anche se una variabile è definita e ha un valore significativo in altre proprietà, come 20px, se il valore non corrisponde a un colore, la dichiarazione del colore diventa invalida al momento del calcolo. In questo caso, non devi aspettarti che var() selezioni il valore di ripiego viola.

Stato della variabile Risultato della dichiarazione del colore Colore nell’esempio completo
--notice-color assente Utilizzo di valori di fallback per var viola
--notice-color è rosso Usare valori definiti rosso
--notice-color è 20px Regole di ereditarietà/valore iniziale applicate perché non corrisponde al colore Poiché color è una proprietà ereditata, usa il colore del testo verde del genitore.

Come mostrato di seguito, anche se c'è una dichiarazione blu prima nella stessa regola, se il valore dopo la sostituzione della variabile nella seconda dichiarazione non corrisponde, non tornerà al primo blu. Dopo che la dichiarazione selezionata nella cascata è invalida al momento della valutazione, vengono applicate le regole di ereditarietà del colore. Nella stessa situazione, una proprietà che non è ereditata può essere trattata come il valore iniziale di quella proprietà. La guida MDN alle proprietà personalizzate spiega la differenza tra valori sostitutivi e valori non validi.

.sample {
  color: #1d5f91;
  color: var(--notice-color, #6a3989);
}
.sample.bad { --notice-color: 20px; }

Puoi anche inserire altre variabili nel valore di fallback. Ad esempio, var(--button-accent, var(--accent, #1d5f91)) cerca il valore da utilizzare, iniziando con il valore specifico del pulsante, poi il valore comune e infine il colore predefinito. Tuttavia, se gli usi di numeri, lunghezze e colori sono mescolati, si verifica lo stesso problema, quindi i nomi delle variabili e il loro utilizzo devono essere gestiti insieme.

Combina valori e unità con calc()

L'esempio moltiplica --space-unit: .5rem per 3 per impostare il padding della scheda. rem utilizza la dimensione del font radice, quindi modificare quella dimensione cambia la spaziatura. Usa calc() per il calcolo invece di concatenare stringhe e lascia spazi intorno agli operatori di addizione e sottrazione. Per ulteriori dettagli, vedi Colori e unità CSS: px, em, rem e percentuali.

:root {
  --space-unit: .5rem;
  --space-card: calc(var(--space-unit) * 3);
}
.card { padding: var(--space-card); }

Scegli coerentemente se le variabili includono unità o solo numeri. Se inserisci un valore senza unità come 2 nella variabile di lunghezza, potrebbe non essere adatto per applicazioni che richiedono unità. Evita combinazioni di usi diversi, come applicare calc a una variabile contenente un colore. Per la sintassi di base della formula, fai riferimento al documento MDN: calc().

Esegui il confronto tra ambito e fallback

Salva il seguente codice come custom-properties.html in UTF-8 e aprilo nel tuo browser. Confronta i colori degli accenti delle due schede e i colori del testo delle tre frasi. Il significato dei colori è stato anche scritto a parole per poter distinguere i risultati anche senza affidarsi soltanto al colore.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>CSS variable scope and substitution values</title>
  <style>
*, *::before, *::after { box-sizing: border-box; }
body { margin: 0; padding: 1rem; color: #183044; font-family: sans-serif; line-height: 1.6; }
main { max-width: 46rem; margin-inline: auto; }
h1 { font-size: 1.5rem; } h2 { font-size: 1.2rem; }
button, input { font: inherit; }
button { cursor: pointer; }
:focus-visible { outline: 3px solid #164f73; outline-offset: 3px; }
:root { --space-unit: .5rem; --space-card: calc(var(--space-unit) * 3); --accent: #1d5f91; }
.cards { display: grid; gap: 1rem; }
.card { --card-accent: var(--accent); padding: var(--space-card); border: 2px solid var(--card-accent);
  border-radius: .5rem; background: #f6f9fb; }
.card h2 { color: var(--card-accent); margin-block: 0 .5rem; }
.card p { margin: 0; }
.card.warning { --card-accent: #a63e32; }
.fallback-area { margin-block: 2rem; padding: 1rem; border: 1px solid #8a9ba7; color: #28633b; }
.sample { color: #1d5f91; color: var(--notice-color, #6a3989); }
.sample.bad { --notice-color: 20px; }
.sample.good { --notice-color: #a63e32; }
  </style>
</head>
<body>
<main>
<h1>Variable scope and fallbacks</h1>
<div class="cards">
  <article class="card"><h2>Basic card</h2><p>The heading and border share the same accent color.</p></article>
  <article class="card warning"><h2>warning card</h2><p>The accent color changes only inside this card.</p></article>
</div>
<section class="fallback-area">
  <h2>The parent's text color is green</h2>
  <p class="sample missing">Undefined: purple fallback</p>
  <p class="sample bad">20px: Doesn't match the color, so it inherits the green color from the parent.</p>
  <p class="sample good">Defined as red: use that color</p>
</section>
</main>
</body>
</html>
  1. Assicurati che il titolo e il bordo delle schede di base siano blu e che le schede di avviso siano rosse. Le tre frasi qui sotto sono rispettivamente colorate di viola, verde e rosso.
  2. Cambia solo l'accento principale in #28633b. L'intestazione e il bordo della scheda predefinita dovrebbero cambiare, mentre la scheda di avviso mantiene il proprio colore di avviso. Ripristina l'accento principale a #1d5f91 dopo il controllo.
  3. Sostituisci soltanto --space-unit con 1rem. Gli spazi interni di entrambe le schede si estendono insieme. Dopo la conferma, ripristina a .5rem.
  4. Cambia solo --notice-color di .sample.bad da 20px a #1d5f91. La frase cambierà da verde a blu. Dopo la conferma, ripristinala a 20px.
  5. Elimina solo la dichiarazione --notice-color di .sample.bad. Questa volta viene utilizzato un fallback viola. Confrontalo con il risultato blu del passaggio precedente e ripristina la dichiarazione originale.

Diagnostica le variabili mancanti o errate

  • Negli strumenti per sviluppatori, verifica se il nome e il valore della variabile esistono effettivamente in quell'elemento. Controlla prima l'ortografia, le maiuscole e minuscole e l’ambito della dichiarazione.
  • Verifica se i discendenti o altre regole sovrascrivono la stessa variabile. Potrebbe non essere un errore se un componente mantiene i suoi valori unici anche se il valore comune cambia.
  • Verifica se la variabile viene richiamata nella proprietà effettiva e se le unità e il tipo del valore sostituito sono corretti.
  • Se un valore viene creato tramite più variabili, controlla su quale elemento avviene il calcolo e quale valore viene ereditato. Evita inoltre dichiarazioni che si riferiscono alla stessa variabile come se stessa o che si riferiscono in modo circolare.

Puoi sfruttare le variabili distinguendo tra colori comuni e spaziatura del design e le eccezioni per ciascun componente, e controllando i risultati prima e dopo la modifica. Piuttosto che aumentare il numero di nomi di variabili, è più utile per la manutenzione rendere chiaro quali valori sono condivisi in quale ambito.