CSS-variabelen, beter bekend als aangepaste CSS-eigenschappen, zijn vanaf nu beschikbaar in Chrome 49. Ze kunnen handig zijn om herhaling in CSS te verminderen en ook voor krachtige runtime-effecten zoals themawisseling en het mogelijk uitbreiden/polyfillen van toekomstige CSS-functies.
CSS-rommel
Bij het ontwerpen van een applicatie is het gebruikelijk om een set merkkleuren te reserveren die hergebruikt worden om de look van de app consistent te houden. Helaas is het steeds opnieuw herhalen van deze kleurwaarden in je CSS niet alleen een vervelende klus, maar ook foutgevoelig. Als een van de kleuren op een gegeven moment moet worden gewijzigd, kun je de voorzichtigheid laten varen en alles "zoeken en vervangen", maar bij een groot project kan dit al snel gevaarlijk worden.
De laatste tijd zijn veel ontwikkelaars overgestapt op CSS-preprocessors zoals SASS of LESS, 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 niet tijdens runtime worden gewijzigd. 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 de mogelijkheid 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
var()
functie, waarmee een auteur deze waarden in andere eigenschappen kan gebruiken.
Hier is een snel voorbeeld om het 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. Let op: alle aangepaste eigenschappen beginnen met twee streepjes.
De var()
functie haalt de aangepaste eigenschapswaarde op en vervangt deze door zichzelf. Dit resulteert in color: #06c;
Zolang de aangepaste eigenschap ergens in uw stijlblad is gedefinieerd, zou deze beschikbaar moeten zijn voor de var
functie.
De syntaxis ziet er in eerste instantie misschien wat vreemd uit. Veel ontwikkelaars vragen zich af: "Waarom gebruiken we niet gewoon $foo
voor variabelenamen?" De aanpak is specifiek gekozen om zo flexibel mogelijk te zijn en in de toekomst mogelijk $foo
macro's mogelijk te maken. Voor de achtergrondinformatie kun je dit bericht lezen van een van de specificatieauteurs, Tab Atkins.
Syntaxis van aangepaste eigenschappen
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 in feite vrij permissief. 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 mogelijk wel gelezen en verwerkt kunnen worden met JavaScript tijdens runtime. Dit betekent dat aangepaste eigenschappen de potentie hebben om allerlei interessante technieken te ontsluiten die momenteel niet mogelijk zijn met de huidige CSS-preprocessors. Dus als je denkt: " gaap, ik heb SASS, dus wat maakt het uit...", kijk dan nog eens goed! Dit zijn niet de variabelen waar je normaal mee werkt.
De waterval
Aangepaste eigenschappen volgen standaard cascaderegels, 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 media queries kunt gebruiken ter ondersteuning van responsief ontwerp. Een voorbeeld hiervan is het uitbreiden van de marges rond uw belangrijkste sectie-elementen naarmate het scherm groter wordt:
:root {
--gutter: 4px;
}
section {
margin: var(--gutter);
}
@media (min-width: 600px) {
:root {
--gutter: 16px;
}
}
Het is belangrijk om te benadrukken dat het bovenstaande codefragment niet mogelijk is met de huidige CSS-preprocessors, die geen variabelen in media queries kunnen definiëren. Deze mogelijkheid biedt echter veel mogelijkheden!
Het is ook mogelijk om aangepaste eigenschappen te hebben die hun waarde ontlenen aan andere aangepaste eigenschappen. Dit kan erg 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 van de functie var()
ziet er als volgt uit:
var(<custom-property-name> [, <declaration-value> ]? )
Waarbij <custom-property-name>
de naam is van een door de auteur gedefinieerde aangepaste eigenschap, zoals --foo
, en <declaration-value>
een fallback-waarde is die gebruikt moet worden wanneer de gerefereerde aangepaste eigenschap ongeldig is. Fallback-waarden kunnen een door komma's gescheiden lijst zijn, die gecombineerd wordt tot één waarde. var(--font-stack, "Roboto", "Helvetica");
definieert bijvoorbeeld een fallback van "Roboto", "Helvetica"
. Houd er rekening mee dat verkorte waarden, zoals die gebruikt worden voor marge en opvulling, niet door komma's gescheiden zijn, dus een geschikte fallback voor opvulling zou er als volgt uitzien.
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 Shadow DOM gebruiken, omdat aangepaste eigenschappen schaduwgrenzen kunnen overschrijden. Een webcomponentauteur kan een eerste ontwerp maken met behulp van fallback-waarden en thematiserings-'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 paar valkuilen waar je 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 weergegeven.
Op dezelfde manier kun je niet (naïef) een waarde opbouwen waarvan een deel door een variabele wordt geleverd:
.foo {
--gap: 20;
margin-top: var(--gap)px;
}
Nogmaals, dit is niet hetzelfde als het instellen van margin-top: 20px;
. Om een waarde op te bouwen, heb je iets anders nodig: de functie calc()
.
Waarden opbouwen met calc()
Als je er nog nooit mee hebt gewerkt, is de calc()
-functie een handig hulpmiddeltje waarmee je berekeningen kunt uitvoeren om CSS-waarden te bepalen. Deze functie wordt ondersteund door alle moderne browsers en kan worden gecombineerd met aangepaste eigenschappen om nieuwe waarden te genereren. Bijvoorbeeld:
.foo {
--gap: 20;
margin-top: calc(var(--gap) * 1px); /* niiiiice */
}
Werken met aangepaste eigenschappen in JavaScript
Als u de waarde van een aangepaste eigenschap tijdens runtime wilt ophalen, gebruikt u de getPropertyValue()
-methode 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 een aangepaste eigenschap tijdens runtime in te stellen, gebruikt u de setProperty()
methode 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 instellen om te verwijzen naar een andere aangepaste eigenschap tijdens runtime 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 stijlblad, kunt u zich voorstellen dat dit allerlei interessante runtime-effecten kan opleveren.
Browserondersteuning
Momenteel ondersteunen Chrome 49, Firefox 42, Safari 9.1 en iOS Safari 9.3 aangepaste eigenschappen.
Demonstratie
Probeer het voorbeeld uit om een idee te krijgen van alle interessante technieken die u nu kunt gebruiken dankzij aangepaste eigenschappen.
Verder lezen
Als u meer wilt weten over aangepaste eigenschappen, heeft Philip Walton van het Google Analytics-team een inleiding geschreven over waarom hij zo enthousiast is over aangepaste eigenschappen. U kunt de voortgang ervan in andere browsers volgen op chromestatus.com .