Variabili CSS: perché dovrebbero interessarti?

Le variabili CSS, note in modo più preciso come proprietà personalizzate CSS, si trovano in Chrome 49. Possono essere utili per ridurre le ripetizioni in CSS e anche per potenti effetti di runtime come il cambio di tema e potenzialmente l'estensione/il polyfilling di future funzionalità CSS.

Disordine CSS

Quando si progetta un'applicazione, è pratica comune mettere da parte un insieme di colori del brand che verranno riutilizzati per mantenere l'aspetto dell'app coerente. Purtroppo, la ripetizione più volte di questi valori nel CSS non è solo un'operazione noiosa, ma anche soggetta a errori. Se, a un certo punto, uno dei colori deve essere modificato, si potrebbe mettere in guardia il vento e "trovare e sostituire" tutte le cose, ma in un progetto abbastanza grande questo potrebbe facilmente diventare pericoloso.

Di recente, molti sviluppatori si sono rivolti a preprocessori CSS come SASS o LESS, che risolvono questo problema attraverso l'uso di variabili del preprocessore. Sebbene questi strumenti abbiano aumentato enormemente la produttività degli sviluppatori, le variabili che utilizzano presentano uno svantaggio importante, ovvero il fatto che sono statiche e non possono essere modificate in fase di runtime. L'aggiunta della possibilità di modificare le variabili in fase di runtime non solo apre le porte a elementi come la tematizzazione dinamica dell'applicazione, ma ha anche importanti implicazioni per il responsive design e la possibilità di eseguire il polyfill delle future funzionalità CSS. Con il rilascio di Chrome 49, queste funzionalità sono ora disponibili sotto forma di proprietà CSS personalizzate.

Panoramica delle proprietà personalizzate

Le proprietà personalizzate aggiungono due nuove funzionalità agli strumenti CSS:

  • La possibilità per un autore di assegnare valori arbitrari a una proprietà con un nome scelto dall'autore.
  • La funzione var(), che consente a un autore di utilizzare questi valori in altre proprietà.

Ecco un breve esempio per dimostrare

:root {
    --main-color: #06c;
}

#foo h1 {
    color: var(--main-color);
}

--main-color è una proprietà personalizzata definita dall'autore con il valore #06c. Tieni presente che tutte le proprietà personalizzate iniziano con due trattini.

La funzione var() recupera e sostituisce il valore della proprietà personalizzata, generando color: #06c;. Finché la proprietà personalizzata è definita da qualche parte nel foglio di stile, deve essere disponibile per la funzione var.

All'inizio la sintassi potrebbe sembrare un po' strana. Molti sviluppatori chiedono: "Perché non usare solo $foo per i nomi delle variabili?" L'approccio è stato scelto appositamente per essere il più flessibile possibile e potenzialmente consentire l'uso di macro $foo in futuro. Per conoscere la storia, puoi leggere questo post scritto da uno degli autori delle specifiche, Tab Atkins.

Sintassi delle proprietà personalizzate

La sintassi di una proprietà personalizzata è semplice.

--header-color: #06c;

Tieni presente che le proprietà personalizzate sono sensibili alle maiuscole, quindi --header-color e --Header-Color sono proprietà personalizzate diverse. Anche se a prima vista possono sembrare semplici, la sintassi consentita per le proprietà personalizzate è piuttosto permissiva. Ad esempio, la seguente è una proprietà personalizzata valida:

--foo: if(x > 5) this.width = 10;

Sebbene non sia utile come variabile, poiché non sarebbe valida in qualsiasi proprietà normale, potrebbe potenzialmente essere letta e utilizzata con JavaScript in runtime. Ciò significa che le proprietà personalizzate hanno il potenziale per sbloccare tutti i tipi di tecniche interessanti non attualmente possibili con i pre-processori CSS attuali. Quindi se pensi "yawn ho SASS quindi chi se ne frega...", dai un'altra occhiata! Non sono le variabili con cui sei abituato a lavorare.

Cascade

Le proprietà personalizzate seguono le regole a cascata standard, quindi puoi definire la stessa proprietà a diversi livelli di specificità

:root { --color: blue; }
div { --color: green; }
#alert { --color: red; }
* { color: var(--color); }
<p>I inherited blue from the root element!</p>
<div>I got green set directly on me!</div>
<div id="alert">
    While I got red set directly on me!
    <p>I’m red too, because of inheritance!</p>
</div>

Ciò significa che puoi sfruttare le proprietà personalizzate all'interno delle query supporti per supportare il design reattivo. Un caso d'uso potrebbe essere quello di espandere i margini intorno gli elementi di sezionamento principali all'aumento delle dimensioni dello schermo:

:root {
    --gutter: 4px;
}

section {
    margin: var(--gutter);
}

@media (min-width: 600px) {
    :root {
    --gutter: 16px;
    }
}

È importante sottolineare che lo snippet di codice riportato sopra non è possibile utilizzando i pre-processori CSS attuali, che non sono in grado di definire variabili all&#39;interno delle query supporti. Questa abilità ti consente di sfruttare un grande potenziale.

È anche possibile avere proprietà personalizzate che ricavano il proprio valore da altre proprietà personalizzate. Questo può essere estremamente utile per i temi:

:root {
    --primary-color: red;
    --logo-text: var(--primary-color);
}

La funzione var()

Per recuperare e utilizzare il valore di una proprietà personalizzata, devi utilizzare la funzione var(). La sintassi per la funzione var() è simile alla seguente:

var(<custom-property-name> [, <declaration-value> ]? )

Dove <custom-property-name> è il nome di una proprietà personalizzata definita dall'autore, come --foo, e <declaration-value> è un valore di riserva da utilizzare quando la proprietà personalizzata a cui viene fatto riferimento non è valida. I valori di riserva possono essere un elenco separato da virgole, che verrà combinato in un unico valore. Ad esempio, var(--font-stack, "Roboto", "Helvetica"); definisce un elemento di riserva "Roboto", "Helvetica". Tieni presente che i valori abbreviati, come quelli utilizzati per i margini e i padding, non sono separati da virgole, quindi un valore alternativo appropriato per il padding sarà simile al seguente.

p {
    padding: var(--pad, 10px 15px 20px);
}

Utilizzando questi valori di riserva, l'autore di un componente può scrivere stili difensivi per il proprio elemento:

/* In the component’s style: */
.component .header {
    color: var(--header-color, blue);
}
.component .text {
    color: var(--text-color, black);
}

/* In the larger application’s style: */
.component {
    --text-color: #080;
    /* header-color isn’t set,
        and so remains blue,
        the fallback value */
}

Questa tecnica è particolarmente utile per i componenti web a tema che utilizzano Shadow DOM, poiché le proprietà personalizzate possono attraversare i confini delle ombre. Un autore di componenti web può creare un design iniziale utilizzando valori di riserva ed esporre &quot;hook&quot; per la tematizzazione sotto forma di proprietà personalizzate.

<!-- In the web component's definition: -->
<x-foo>
    #shadow
    <style>
        p {
        background-color: var(--text-background, blue);
        }
    </style>
    <p>
        This text has a yellow background because the document styled me! Otherwise it
        would be blue.
    </p>
</x-foo>
/* In the larger application's style: */
x-foo {
    --text-background: yellow;
}

Quando usi var(), ci sono alcune cose a cui fare attenzione. Le variabili non possono essere nomi di proprietà. Ad esempio:

.foo {
    --side: margin-top;
    var(--side): 20px;
}

Tuttavia, non è equivalente all'impostazione margin-top: 20px;. La seconda dichiarazione, invece, non è valida e viene ignorata come errore.

Analogamente, non puoi (ingenuamente) creare un valore di cui una parte è fornita da una variabile:

.foo {
    --gap: 20;
    margin-top: var(--gap)px;
}

Anche in questo caso, non equivale a impostare margin-top: 20px;. Per creare un valore, hai bisogno di qualcos'altro: la funzione calc().

Creazione di valori con calc()

Se non hai mai lavorato con questa funzionalità prima d'ora, la funzione calc() è un piccolo strumento che consente di eseguire calcoli per determinare i valori CSS. È supportato su tutti i browser moderni e può essere combinato con proprietà personalizzate per creare nuovi valori. Ad esempio:

.foo {
    --gap: 20;
    margin-top: calc(var(--gap) * 1px); /* niiiiice */
}

Utilizzo delle proprietà personalizzate in JavaScript

Per ottenere il valore di una proprietà personalizzata in fase di esecuzione, utilizza il getPropertyValue() metodo dell'oggetto CSSStyleDeclaration calcolato.

/* CSS */
:root {
    --primary-color: red;
}

p {
    color: var(--primary-color);
}
<!-- HTML -->
<p>I’m a red paragraph!</p>
/* JS */
var styles = getComputedStyle(document.documentElement);
var value = String(styles.getPropertyValue('--primary-color')).trim();
// value = 'red'

Analogamente, per impostare il valore della proprietà personalizzata in fase di esecuzione, utilizza il metodo setProperty() dell'oggetto CSSStyleDeclaration.

/* CSS */
:root {
    --primary-color: red;
}

p {
    color: var(--primary-color);
}
<!-- HTML -->
<p>Now I’m a green paragraph!</p>
/* JS */
document.documentElement.style.setProperty('--primary-color', 'green');

Puoi anche impostare il valore della proprietà personalizzata in modo che faccia riferimento a un'altra proprietà personalizzata in fase di runtime utilizzando la funzione var() nella chiamata a setProperty().

/* CSS */
:root {
    --primary-color: red;
    --secondary-color: blue;
}
<!-- HTML -->
<p>Sweet! I’m a blue paragraph!</p>
/* JS */
document.documentElement.style.setProperty('--primary-color', 'var(--secondary-color)');

Poiché le proprietà personalizzate possono fare riferimento ad altre proprietà personalizzate nei tuoi fogli di stile, puoi immaginare come questo possa portare a tutti i tipi di effetti di runtime interessanti.

Supporto browser

Al momento, Chrome 49, Firefox 42, Safari 9.1 e iOS Safari 9.3 supportano le proprietà personalizzate.

Demo

Prova il sample per dare un'occhiata a tutte le tecniche interessanti che ora puoi sfruttare grazie alle proprietà personalizzate.

Per approfondire

Se ti interessa saperne di più sulle proprietà personalizzate, Philip Walton del team di Google Analytics ha scritto un'introduzione al motivo per cui è impaziente delle proprietà personalizzate. Puoi controllare i progressi in altri browser all'indirizzo chromestatus.com.