
Websites thematiseren met CSS variabelen inclusief tips
Er was een tijd dat een 1024 pixel grid alles was waar we onze webapps voor ontwikkelden, maar die tijd is allang voorbij. En er was een tijd dat de kleuren in onze app vaststonden en een directe kopie waren van een PSD, ook die tijd is voorbij. Gebruikers verwachten dat applicaties vloeiend zijn en zich aanpassen aan hen en hun apparaten. Gebruik je een donker Windows-thema? Dan zou de app dat ook moeten doen. Toegankelijkheid is ook ontzettend belangrijk voor ontwikkelaars, en thematisering kan ons helpen gebruikers met een kleurenzienstoornis (CVD) beter te bedienen.
In deze post laat ik een snelle en eenvoudige manier zien om thema’s te implementeren in je frontend-applicaties.
De oude manier van doen
Voordat ik de code laat zien, een korte blik op het verleden. Tijdens het jQuery-tijdperk implementeerden we thema’s door een className toe te voegen aan de body van de HTML. Bijvoorbeeld de class .red als overridende CSS-selector. De code zag er ongeveer zo uit:
JS:
document.getElementByTagName('body').className.add('red')
CSS:
.background { background-color: white; } .red .background { background-color: red; }
In dit voorbeeld verandert zodra de class red aan de body wordt toegevoegd, de kleur van alle onderliggende selectors.
Het probleem met geneste classes
Dit creëert twee problemen. Ten eerste wordt onderhoud van de app lastiger omdat je elke class die van kleur kan veranderen dubbel moet definiëren. Heeft je app 1000 classes, dan zijn dat er 2000 als je klaar bent. Dit zijn CSS-classes die je moet onderhouden en aanpassen als de code terugkomt van design of UX. Natuurlijk zouden we hiervoor SCSS maps en functies kunnen gebruiken, en dat zouden we waarschijnlijk ook moeten doen, maar het blijft een extra complexiteit die we moeten beheren.
Ten tweede schaalt deze aanpak helemaal niet. Onze CSS-code wordt steeds groter met elk thema dat we toevoegen. Een load van 30kb wordt zo ~36kb. (Het wordt niet precies het dubbele omdat we alleen kleurveranderingen declareren), maar het loopt snel op. 12 thema’s wordt dan 30 + 6 * 12 = 102kb. Dat is een 4x zo grote bestandsgrootte.
Oplossing
De oplossing is het gebruik van CSS-variabelen, die tegenwoordig door vrijwel alle browsers worden ondersteund (CSS Variables (Custom Properties) | Can I use… Support tables for HTML5, CSS3, etc)
Declareer eerst je thema. Mijn enige regel is dat keys niet mogen veranderen en hun gebruik heel duidelijk moeten omschrijven. Een HTML-card kan bijvoorbeeld de volgende kleuren hebben:
cardBackground: #ffffff cardBorder: #444444 cardText: #444444
Een mindere oplossing:
background: #ffffff border: #444444 text: #444444
Hoewel dat ook kan, wordt het onmogelijk om de card-achtergrond los van de algemene app-achtergrond te veranderen. Dat kan prima zijn, maar denk vooruit aan nuttige overrides.
In je code ziet de styling er ongeveer zo uit:
HTML:
:root { --cardBackground: #ffffff; --cardBorder: #444444; --cardText: #444444 }
CSS
.card { background-color: var(--cardBackground, #ffffff) }
JS
document.getElementByTagName('body').appendStyle('new values here')
Eerst injecteren we alle variabelen met een waarde in de root van de HTML. Dit maakt ze toepasbaar op al onze CSS-classes. Je kunt de variabelen ook toevoegen aan een geneste class (bijvoorbeeld een div, .card, etc), maar dan zijn ze alleen beschikbaar voor de child-elementen, en dat willen we meestal niet.
Vervolgens refereren we in onze classes naar deze variabelen, en voegen een fallback waarde toe voor het geval de variabele niet gevonden wordt. Dat is de tweede waarde in var(--variable, fallback).
Waarom dit top is
Dit is fantastisch omdat we onze CSS schoon en droog kunnen houden en oneindige themamogelijkheden kunnen toevoegen zonder de grootte van onze CSS te vergroten. Daarnaast kunnen kleuren realtime veranderen zonder herladen of extra bestanden ophalen. Bekijk dit voorbeeldrepo om de code in actie te zien.
Conclusie
Theming wordt een steeds belangrijker aspect van applicatieontwikkeling. Het kan toegankelijkheidsproblemen oplossen, kwaliteitsverbeteringen zoals een dark mode bieden, of een white label product mogelijk maken voor leveranciers.
We bereiken dit door geneste CSS-classes te vermijden en in plaats daarvan CSS-variabelen te gebruiken. Deze kunnen in de HTML worden gezet en tijdens runtime aangepast worden. Deze truc stelt ons in staat een schone thematiseringsoplossing met oneindige schaalbaarheid voor onze webapps te leveren. Dank je wel, CSS-variabelen :)