CSS-variabelen - Waarom zou u zich zorgen maken?

CSS-variabelen, beter bekend als aangepaste CSS-eigenschappen, komen terecht in Chrome 49. Ze kunnen nuttig zijn om herhaling in CSS te verminderen, en ook voor krachtige runtime-effecten zoals het wisselen van thema en het mogelijk uitbreiden/polyfillen van toekomstige CSS-functies.

CSS-rommel

Bij het ontwerpen van een applicatie is het gebruikelijk om een ​​reeks merkkleuren opzij te zetten die hergebruikt kunnen worden om het uiterlijk van de app consistent te houden. Helaas is het keer op keer herhalen van deze kleurwaarden in je CSS niet alleen een hele klus, maar ook foutgevoelig. Als op een gegeven moment een van de kleuren moet worden veranderd, kun je voorzichtig zijn en alle dingen 'zoeken en vervangen', maar bij een project dat groot genoeg is, kan dit gemakkelijk gevaarlijk worden.

De laatste tijd hebben veel ontwikkelaars zich tot CSS-preprocessors zoals SASS of LESS gewend, die dit probleem oplossen door het gebruik van preprocessorvariabelen. Hoewel deze tools de productiviteit van ontwikkelaars enorm hebben verhoogd, hebben de variabelen die ze gebruiken een groot nadeel: ze zijn statisch en kunnen tijdens runtime niet worden gewijzigd. Het toevoegen van de mogelijkheid om variabelen tijdens runtime te wijzigen opent niet alleen de deur naar zaken als dynamische applicatiethema's, maar heeft ook grote gevolgen voor responsief ontwerp en het potentieel om toekomstige CSS-functies te polyfillen. Met de release van Chrome 49 zijn deze mogelijkheden nu beschikbaar in de vorm van aangepaste CSS-eigenschappen.

Aangepaste eigenschappen in een notendop

Aangepaste eigenschappen voegen twee nieuwe functies toe aan onze CSS-toolbox:

  • De mogelijkheid voor een auteur om willekeurige waarden toe te wijzen aan een eigenschap met een door de auteur gekozen naam.
  • De functie var() , waarmee een auteur deze waarden in andere eigenschappen kan gebruiken.

Hier is een snel voorbeeld om te demonstreren

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

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

--main-color is een door de auteur gedefinieerde aangepaste eigenschap met de waarde #06c. Houd er rekening mee dat alle aangepaste eigenschappen beginnen met twee streepjes.

De functie var() haalt zichzelf op en vervangt zichzelf door de aangepaste eigenschapswaarde, wat resulteert in color: #06c; Zolang de aangepaste eigenschap ergens in uw stylesheet is gedefinieerd, zou deze beschikbaar moeten zijn voor de var -functie.

De syntaxis ziet er in eerste instantie misschien een beetje vreemd uit. Veel ontwikkelaars vragen zich af: "Waarom gebruiken we niet gewoon $foo voor de namen van variabelen?" Er is specifiek voor deze aanpak gekozen om zo flexibel mogelijk te zijn en in de toekomst mogelijk $foo macro's mogelijk te maken. Voor het achtergrondverhaal kun je dit bericht lezen van een van de spec-auteurs, Tab Atkins.

Aangepaste eigenschapsyntaxis

De syntaxis voor een aangepaste eigenschap is eenvoudig.

--header-color: #06c;

Houd er rekening mee dat aangepaste eigenschappen hoofdlettergevoelig zijn, dus --header-color en --Header-Color zijn verschillende aangepaste eigenschappen. Hoewel ze op het eerste gezicht eenvoudig lijken, is de toegestane syntaxis voor aangepaste eigenschappen eigenlijk behoorlijk tolerant. Het volgende is bijvoorbeeld een geldige aangepaste eigenschap:

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

Hoewel dit niet nuttig zou zijn als variabele, omdat het ongeldig zou zijn in elke normale eigenschap, zou het tijdens runtime mogelijk kunnen worden gelezen en actie kunnen ondernemen met JavaScript. Dit betekent dat aangepaste eigenschappen het potentieel hebben om allerlei interessante technieken te ontsluiten die momenteel niet mogelijk zijn met de huidige CSS-preprocessors. Dus als je denkt: " Geeuw, ik heb SASS, dus wat maakt het uit...", kijk dan nog eens goed! Dit zijn niet de variabelen waarmee u gewend bent te werken.

De cascade

Aangepaste eigenschappen volgen de standaardcascaderegels, zodat u dezelfde eigenschap op verschillende specificiteitsniveaus kunt definiëren

: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>

Dit betekent dat u aangepaste eigenschappen binnen mediaquery's kunt gebruiken om te helpen bij responsief ontwerp. Eén gebruiksscenario zou kunnen zijn om de marges rond uw belangrijkste snij-elementen uit te breiden naarmate de schermgrootte groter wordt:

:root {
    --gutter: 4px;
}

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

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

Het is belangrijk om erop te wijzen dat het bovenstaande codefragment niet mogelijk is met de hedendaagse CSS-preprocessors, die niet in staat zijn variabelen binnen mediaquery's te definiëren. Als je deze vaardigheid hebt, ontgrendel je veel potentieel!

Het is ook mogelijk om aangepaste eigenschappen te hebben die hun waarde ontlenen aan andere aangepaste eigenschappen. Dit kan uiterst handig zijn voor thema's:

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

De var()-functie

Om de waarde van een aangepaste eigenschap op te halen en te gebruiken, moet u de functie var() gebruiken. De syntaxis voor de functie var() ziet er als volgt uit:

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

Waar <custom-property-name> de naam is van een door de auteur gedefinieerde aangepaste eigenschap, zoals --foo , en <declaration-value> een reservewaarde is die moet worden gebruikt wanneer de aangepaste eigenschap waarnaar wordt verwezen ongeldig is. Reservewaarden kunnen een door komma's gescheiden lijst zijn, die wordt gecombineerd tot één waarde. Bijvoorbeeld var(--font-stack, "Roboto", "Helvetica"); definieert een terugval van "Roboto", "Helvetica" . Houd er rekening mee dat verkorte waarden, zoals die worden gebruikt voor marge en opvulling, niet door komma's worden gescheiden, dus een geschikte terugval voor opvulling zou er als volgt uit kunnen zien.

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

Met behulp van deze fallback-waarden kan een componentauteur defensieve stijlen voor zijn element schrijven:

/* 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 */
}

Deze techniek is vooral handig voor het thematiseren van webcomponenten die gebruik maken van Shadow DOM, omdat aangepaste eigenschappen schaduwgrenzen kunnen overschrijden. Een auteur van een webcomponent kan een initieel ontwerp maken met behulp van terugvalwaarden, en thematische ‘hooks’ blootleggen in de vorm van aangepaste eigenschappen.

<!-- 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;
}

Bij het gebruik van var() zijn er een aantal valkuilen waar u op moet letten. Variabelen kunnen geen eigenschapsnamen zijn. Bijvoorbeeld:

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

Dit is echter niet hetzelfde als het instellen van margin-top: 20px; . In plaats daarvan is de tweede declaratie ongeldig en wordt deze als fout weggegooid.

Op dezelfde manier kun je (naïef) geen waarde opbouwen waarvan een deel wordt geleverd door een variabele:

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

Nogmaals, dit is niet hetzelfde als het instellen margin-top: 20px; . Om een ​​waarde op te bouwen heb je iets anders nodig: de calc() functie.

Waarden opbouwen met calc()

Als u er nog nooit eerder mee hebt gewerkt: de functie calc() is een handig klein hulpmiddel waarmee u berekeningen kunt uitvoeren om CSS-waarden te bepalen. Het wordt ondersteund in alle moderne browsers en kan worden gecombineerd met aangepaste eigenschappen om nieuwe waarden op te bouwen. Bijvoorbeeld:

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

Werken met aangepaste eigenschappen in JavaScript

Om de waarde van een aangepaste eigenschap tijdens runtime op te halen, gebruikt u de methode getPropertyValue() van het berekende CSSStyleDeclaration-object.

/* 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'

Om de waarde van de aangepaste eigenschap tijdens runtime in te stellen, gebruikt u op dezelfde manier de methode setProperty() van het CSSStyleDeclaration object.

/* 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');

U kunt de waarde van de aangepaste eigenschap ook zo instellen dat deze tijdens runtime naar een andere aangepaste eigenschap verwijst door de functie var() te gebruiken in uw aanroep van 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)');

Omdat aangepaste eigenschappen kunnen verwijzen naar andere aangepaste eigenschappen in uw stylesheets, kunt u zich voorstellen hoe dit tot allerlei interessante runtime-effecten kan leiden.

Browser-ondersteuning

Momenteel ondersteunen Chrome 49, Firefox 42, Safari 9.1 en iOS Safari 9.3 aangepaste eigenschappen.

Demo

Probeer het voorbeeld uit en ontdek alle interessante technieken die u nu kunt gebruiken dankzij aangepaste eigenschappen.

Verder lezen

Als u meer wilt weten over aangepaste eigenschappen: Philip Walton van het Google Analytics-team heeft een inleiding geschreven over waarom hij enthousiast is over aangepaste eigenschappen. U kunt hun voortgang in andere browsers volgen op chromestatus.com .