Zelfs in 2021 blijven webprestaties een probleem. Volgens HTTP Archive vereist de gemiddelde pagina een download van 2MB, doet deze meer dan 60 HTTP verzoeken en kan het 18 seconden duren om volledig op een mobiel apparaat te laden. Stylesheets zijn goed voor slechts 60 kB – verdeeld over zeven verzoeken – dus ze zijn zelden een topprioriteit bij het oplossen van prestatieproblemen.

Toch heeft CSS wel degelijk een effect, hoe klein het ook lijkt. Zodra je je JavaScript hebt geoptimaliseerd, zou het leren om CSS op de juiste manier te optimaliseren de volgende prioriteit moeten zijn.

Laten we ermee bezig gaan!

Zo beïnvloedt CSS de prestaties van je pagina’s

CSS ziet er misschien onschuldig uit, maar het verwerken ervan kan zeker wat verwerkingskracht kosten.

CSS is render-blocking

Wanneer je browser een <link> tag tegenkomt, stopt het alle andere browserdownloads en -verwerkingen terwijl deze het CSS ophaalt en parset.

JavaScript kan ook het renderen van de browser blokkeren, maar asynchrone verwerking is mogelijk met:

  1. Het async attribuut om scripts parallel te downloaden, die worden uitgevoerd zodra ze klaar zijn.
  2. Het defer attribuut om parallel te downloaden en vervolgens op volgorde uit te voeren wanneer de DOM gereed is.
  3. Het type="module" attribuut om een ES module te laden (die zich gedraagt als defer).

Assets zoals afbeeldingen vereisen vaak meer bandbreedte, maar er zijn efficiënte formats beschikbaar en je kan ze lazyloaden (loading="lazy" attribuut) zonder de browserweergave te blokkeren.

Dit is allemaal niet mogelijk met CSS. Het bestand wordt in de cache opgeslagen, dus volgende pagina’s zouden sneller moeten worden geladen, maar het render-blocking proces blijft een issue.

Het verwerken van grote CSS bestanden kost tijd

Hoe groter je stylesheet, hoe langer het duurt om deze te downloaden en te verwerken in een CSS Object Model (CSSOM), dat de browser en JavaScript API’s kunnen gebruiken om de pagina weer te geven. Hoewel CSS stylesheets kleiner zijn dan de meeste andere websitebestanden, zijn ze niet immuun voor de vuistregel ‘kleiner is beter’.

CSS bestanden groeien

Het kan moeilijk zijn om stijlen te identificeren die niet meer worden gebruikt, en het verwijderen van de verkeerde kan grote schade aanrichten op een site. Ontwikkelaars kiezen doorgaans voor de benadering van “alles houden”. Paginastijlen, componenten en widgets die niet meer worden gebruikt, blijven dus achter in de CSS. Het resultaat? De bestandsgrootte, complexiteit én de tijd die het kost om alles te onderhouden groeit exponentieel, waardoor ontwikkelaars steeds minder snel overbodige code zullen verwijderen.

Stylesheets kunnen verwijzen naar andere assets

CSS kan verwijzen naar andere stylesheets met behulp van @import regels. Deze imports blokkeren de verwerking van de huidige stylesheet en het laden van verdere CSS bestanden in serie.

Er kan ook naar andere assets worden verwezen, zoals lettertypen en afbeeldingen. De browser zal proberen downloads te optimaliseren, maar bij twijfel haalt hij ze onmiddellijk op. Inline base64-encoded bestanden worden nog verder verwerkt.

CSS beïnvloedt rendering

Browsers hebben drie rendering-fasen:

  1. De layout (of reflow) fase berekent de afmetingen van elk element en hoe dit de grootte of positionering van elementen eromheen beïnvloedt.
  2. De paint fase haalt de visuele delen van elk element naar afzonderlijke lagen: tekst, kleuren, afbeeldingen, randen, schaduwen, etc.
  3. De composite fase plaatst elke laag op de pagina in de juiste volgorde, op basis van stackingcontexts, positionering, z-indexen, etc.

Als je niet oppast, kunnen wijzigingen in CSS properties en animaties ervoor zorgen dat alle drie de fasen opnieuw moeten worden gerenderd. Sommige eigenschappen (properties), zoals schaduwen en gradients, kosten meer computerkracht dan bijvoorbeeld blokkleuren en marges.

Analysetools CSS performance

Toegeven dat je een CSS prestatieprobleem hebt, is de eerste stap op weg naar herstel! Het vinden en verhelpen van de oorzaken is een andere zaak.

De volgende tools en diensten (niet in willekeurige volgorde gerangschikt) kunnen je helpen bij het identificeren van knelpunten in je code.

1. DevTools Network paneel

Specialisten op het gebied van webprestaties besteden veel tijd binnen DevTools en het Network paneel in het bijzonder. DevTools is ingebouwd in de meeste moderne browsers, hoewel we in onze voorbeelden Google Chrome zullen gebruiken.

DevTools kan worden geopend vanuit het browsermenu, normaal gesproken via More tools > Developer tools of via de sneltoetsen Ctrl | Cmd + Shift + I of F12.

Schakel over naar het Network tabblad en zorg ervoor dat Disable cache is aangevinkt om te voorkomen dat gecachete bestanden het rapport beïnvloeden. Je kan ook de “throttling” optie wijzigen om langzamere mobiele netwerken te simuleren.

Vernieuw de pagina om de watervalgrafiek van downloads en verwerking te bekijken:

DevTools Network paneel
DevTools Network paneel

Elke lange balk is een reden tot bezorgdheid, maar je moet vooral op je hoede zijn voor lange geblokkeerde/vastgelopen balkjes (weergegeven in het wit). In dit voorbeeld konden de gemarkeerde rij en alle volgende rijen niet worden gedownload totdat de render-blocking CSS- en JavaScript bestanden bovenaan de HTML pagina waren verwerkt.

Met het Filter vak kan je specifieke items weergeven of verbergen:

  • larger-than:<S>: Beperk tot bestanden groter dan <S>, uitgedrukt als bytes (10,000), Kilobytes (1,000 kB), of megabytes (1 M)
  • -larger-than:<S>: Beperk tot bestanden kleiner dan <S>
  • -domain:*<.jouwdomein.com>: Toon externe verzoeken die niet vanuit je hoofddomein zijn geladen. Deze zijn vaak een belangrijke oorzaak van trage sites.

Een high-performance pagina met geoptimaliseerde CSS heeft doorgaans minder items die parallel worden geladen met korte geblokkeerde/vastgelopen balken.

2. WebPageTest.org

WebPageTest biedt een vergelijkbare netwerk-watervalgrafiek, naast heel veel andere prestatiegrafieken:

WebPageTest.org asset waterval
WebPageTest.org asset waterval

De service maakt gebruik van apparaten op verschillende locaties wereldwijd, zodat je de real-world prestaties en CSS optimalisaties kan beoordelen.

3. Chrome DevTools Lighthouse paneel

Het DevTools Lighthouse paneel wordt geleverd in op Chromium gebaseerde browsers zoals Chrome, Edge, Brave, Opera en Vivaldi. Je kan voor zowel mobiele als desktopapparaten verschillende rapporten genereren: Performance, Progressive Web App, Best Practices, Accessibility en Search Engine Optimalisation.

Devtools Lighthouse paneel
Devtools Lighthouse paneel

De tool doet suggesties voor verbeteringen, waaronder manieren om CSS te optimaliseren. Niet alles is misschien even praktisch of haalbaar, maar gelukkig wordt het laaghangend fruit voor je gehighlight.

4. Google PageSpeed Insights

PageSpeed Insights is de online versie van Lighthouse. Het heeft minder functies, maar kan in elke browser worden gebruikt en biedt een aantal alternatieve inzichten.

Een treemap toont bijvoorbeeld de grootste JavaScript assets met een dekkingsmetric, die aangeeft welk deel van de code wordt gebruikt en elke niet:

Treemap van Google PageSpeed Insights
Treemap van Google PageSpeed Insights

CSS wordt niet weergegeven, maar de hoeveelheid JavaScript is van invloed op de efficiëntie van stijlen.

Vergelijkbare tools voor het testen van websitesnelheid zijn Pingdom Website Speed Test en GTMetrix.

5. Chrome DevTools Coverage paneel

Het Devtools Coverage paneel in op Chromium gebaseerde browsers helpt je bij het vinden van ongebruikte CSS (en JavaScript) code. Selecteer Coverage van het DevTools submenu More tools en ververs vervolgens je pagina en blader door je site/applicatie:

DevTools Coverage paneel
DevTools Coverage paneel

CSS en JavaScript assets worden weergeven in het paneel Coverage, met het aandeel ongebruikte code in rood. Klik op een bestand om de bron te bekijken met de ongebruikte code rood gemarkeerd op de plek waar je het regelnummer ziet.

Een paar dingen om op te letten:

  • De coveragemetric wordt gereset als je vernieuwt of naar een nieuwe pagina navigeert, zoals gebruikelijk is op een WordPress site. De metric met ongebruikte code neemt alleen af als je door een toepassing met één pagina bladert die content laadt zonder een paginavernieuwing.
  • De tool analyseert alleen CSS die tot een specifiek tijdstip is gebruikt. Het kan niet bepalen of een widget wel of niet bekeken is en of deze meerdere JavaScript-gebonden states heeft.

6. Chrome DevTools Real-Time Performance Monitor

Op Chromium gebaseerde browsers hebben een realtime Performance Monitor. Ook deze is beschikbaar in het More tools menu van DevTools. De grafieken worden bijgewerkt terwijl je door pagina’s navigeert, scrolt en animaties activeert:

DevTools Real-Time Performance Monitor
DevTools Real-Time Performance Monitor

De volgende statistieken zijn van bijzonder belang om de CSS performance te optimaliseren (hoe lager, hoe beter):

  • CPU usage: processorgebruik van 0% tot 100%.
  • Layouts/sec: de snelheid waarmee de browser de layout van de pagina opnieuw moet indelen.
  • Style recalcs/sec: de snelheid waarmee de browser stijlen moet herberekenen.

De andere statistieken kunnen ook nuttig zijn als CSS worstelt vanwege externe factoren (nogmaals, lagere waarden duiden op betere prestaties):

  • JS heap size: het totale geheugen dat wordt gebruikt door JavaScript objecten.
  • DOM Nodes: Het aantal elementen in het HTML document.
  • JS event listeners: het aantal geregistreerde JavaScript event listeners.
  • Documents: het aantal resources, inclusief de pagina, CSS bestanden, JavaScript modules, etc.
  • Document Frames: het aantal frames, iframes en JavaScript worker scripts.

7. DevTools Performance rapport

Met het DevTools Performance paneel kan je pagina-activiteiten opnemen voor verdere analyse en prestatieproblemen helpen identificeren. De gegenereerde rapporten zijn complex en veel ontwikkelaars vermijden ze om die reden, maar ze bieden wel degelijk waardevolle informatie.

Met het instellingenpictogram van het Performance paneel kan je verschillende opties instellen, zoals het vertragen van het netwerk en de CPU. Je kan ook JavaScript samples uitschakelen, zodat gedetailleerde call stacks niet worden opgenomen.

Klik om te beginnen op het ronde pictogram Record en laad/gebruik vervolgens je pagina en klik op de Stop knop om het rapport te zien:

DevTools Performance rapport
DevTools Performance rapport

Bijna al deze statistieken zijn nuttig voor JavaScript ontwikkelaars, maar wat CSS optimalisatie betreft kan je het beste kijken naar:

  • Rode balk bovenaan: deze geeft aan dat de framerate aanzienlijk is gedaald, wat prestatieproblemen kan veroorzaken.  Dit wordt verwacht aan het begin van het laden van een pagina, maar overmatige CSS animaties kunnen ook een probleem zijn.
  • Overzichtstabel: hoge laad-, rendering-, en paintingstatistieken kunnen wijzen op een CSS probleem.

Indirecte CSS prestatieverbeteringen

De volgende fixes lossen CSS problemen niet meteen op, maar ze kunnen wel helpen om een paar veelvoorkomende prestatieproblemen met relatief weinig inspanning op te lossen.

Gebruik een goede host

Het gebruik van een goede host met servers die fysiek dichter bij je gebruikers staan, zal onmiddellijke prestatievoordelen opleveren. Hostingpakketten kunnen variëren, maar er zijn drie hoofdtypen:

  1. Gedeelde hosting: je website wordt gehost op een fysieke server, mogelijk samen met honderden andere sites. Schijfruimte, RAM, CPU tijd en bandbreedte wordt gedeeld. Abonnementen zijn vaak niet duur, maar de prestaties en beschikbaarheid worden beïnvloed door andere sites. Upgraden is soms mogelijk, maar je site blijft over het algemeen binnen dezelfde infrastructuur.
  2. Dedicated hosting: je site wordt gehost op een of meerdere fysieke servers die jij zelf bezit. De hardware kan naar wens worden geconfigureerd en geüpgraded. Abonnementen zijn vaak duur en problemen met hardware kunnen problematisch zijn.
  3. Cloudhosting: Cloudhosting transformeert de hardware-infrastructuur tot een reeks diensten die on-demand toegankelijk zijn. Je site kan op verschillende apparaten worden ingericht om upgrades eenvoudig te maken.

De pakketten en prijzen van cloudhosting kunnen enorm variëren. Je zou kunnen overwegen:

  1. Platform as a Service (PaaS) opties, zoals virtuele webservers en databases, of
  2. Software as a Service (SaaS) opties, die volledig managed applicaties zoals WordPress

Het wisselen van host kan de prestaties verbeteren. Het is onwaarschijnlijk dat dat het al je problemen oplost, maar het is een kosteneffectieve oplossing voor zowel problemen in de backend als met bandbreedte.

Je kan overwegen om een content delivery network (CDN) of een gespecialiseerd afbeeldings- en video CDN te gebruiken dat de belasting kan verdelen over meerdere locaties die geografisch dichter bij je gebruikers liggen.

Maak gebruik van de efficiëntiefeatures van browsers en servers

Ongeveer 10% van de sites activeert geen gzip (of betere) compressie, wat meestal de standaard serveroptie is. Het gebruik ervan vermindert de grootte van CSS met 60% of meer door bestanden te comprimeren voordat ze worden verzonden. Het lost inefficiënte CSS niet op, maar de code zal wel eerder aankomen!

Ook zou je HTTP/2 kunnen activeren (of beter) dat gegevens in een kleinere binaire indeling verstuurt, de headers comprimeert, zodat meer dan één bestand kan worden verzonden binnen dezelfde TCP verbinding.

Zorg er ten slotte voor dat de browser CSS en andere bestanden effectief kan cachen. Dit is meestal een kwestie van het instellen van Expires, last-modified en/of ETag hashes in de HTTP header.

Optimaliseer je CMS

Content management systemen zoals WordPress kunnen worden uitgebreid met thema’s en plugins die van hun eigen CSS gebruikmaken. Waar moet zou je je CMS moeten versnellen door:

  1. Ongebruikte plugins te verwijderen.
  2. Slankere thema’s te gebruiken
  3. Caching in te schakelen om overmatige paginaregeneratie te voorkomen.

Optimaliseer je afbeeldingen

Afbeeldingen hebben niet dezelfde verwerkings- en weergave-overhead als HTML, CSS en JavaScript, maar nemen een groot deel van het paginagewicht en de bruikbare bandbreedte voor hun rekening. Overweeg:

  1. Het verwijderen van onnodige afbeeldingen.
  2. Het resizen van grotere afbeeldingen – misschien tot niet meer dan 150% van de maximale waarmee ze ooit op een scherm kunnen verschijnen.
  3. Het gebruik van een geschikte afbeeldingsindeling – idealiter een sterk gecomprimeerde optie zoals WebP of VIF, en mogelijk SVG voor logo’s en grafieken.
  4. Het vervangen van afbeeldingen door CSS gradients of andere effecten.
  5. Het toevoegen van width en height attributen aan de HTML <img> of het gebruik van de nieuwe CSS aspect-ratio property om ervoor te zorgen dat er voldoende ruimte op de pagina wordt gereserveerd voordat de afbeelding wordt gedownload.

Een gespecialiseerd CDN voor afbeeldingen kan een deel van dit werk voor je uit handen nemen. Raadpleeg voor meer tips onze handleiding over het optimaliseren van afbeeldingen voor het internet.

Verwijder ongebruikte CSS

De snelste stijlen zijn de stijlen die je nooit hoeft te laden of te renderen! Probeer CSS code die je niet langer nodig hebt te verwijderen/bewerken, zoals voor verouderde pagina’s, widgets of frameworks. Dit kan lastig zijn op grotere sites, en het is niet altijd duidelijk of een bepaalde set stijlen essentieel is of niet.

De volgende tools analyseren het HTML en CSS gebruik tijdens build-time of door URL’s te crawlen om overtollige code te identificeren. Dit is niet altijd voldoende, dus er kunnen aanvullende configuraties worden ingesteld om ervoor te zorgen dat stijlen die worden geactiveerd door JavaScript en gebruikersinteracties worden vermeld:

Er is een betere optie: split CSS in afzonderlijke bestanden met duidelijke verantwoordelijkheidsniveaus en documenteer dienovereenkomstig. Het verwijderen van onnodige stijlen wordt dan aanzienlijk eenvoudiger.

Laadprestaties van CSS optimaliseren

Niet alle CSS wordt met dezelfde prioriteit geladen. De <link> tag heeft een aantal opties en eigenaardigheden die niet altijd logisch zijn.

Optimaliseer het gebruik van weblettertypen

Google Fonts en vergelijkbare lettertypewebsites hebben een revolutie teweeggebracht in weblettertypen, maar een paar regels lettertypecode kunnen honderden kilobytes aan bandbreedte opleveren.

Dit zijn onze optimalisatiesuggesties:

  1. Laad alleen de lettertypen die je nodig hebt: verwijder lettertypen die je niet gebruikt en controleer of er nieuwe lettertypen nodig zijn.
  2. Laad alleen de weights en stijlen die je nodig hebt: de meeste lettertypesites kunnen het downloaden beperken tot bepaalde tekensets (zoals alleen Latin), weights (diktes) en italics (slants). Browsers kunnen ontbrekende stijlen automatisch weergeven, hoewel de resultaten slecht kunnen zijn.
  3. Beperk de vereiste tekens: Niet vaak gebruikte lettertypen kan je beperken tot specifieke tekens. De titel ” CSS tutorial” in Open Sans kan worden gedefinieerd door het toevoegen van een &text= parameter aan de Google fonts query string: fonts.googleapis.com/css?family=Open+Sans&text=CStuorial
  4. Overweeg variabele lettertypen: Variabele lettertypen definiëren een grote verscheidenheid aan stijlen, weights, en italics met behulp van vectorinterpolatie. Het lettertypebestand is iets groter, maar je hebt er maar een nodig in plaats van meerdere. Het recursieve lettertype demonstreert de flexibiliteit van variabele lettertypen.
  5. Laad lettertypen van je lokale server: Zelf-gehoste lettertypen zijn efficiënter dan ze te gebruiken van een “font foundry”. Er zijn minder DNS lookups nodig en je kan de download beperken tot WOFF2, die alle moderne browsers ondersteunen. Oudere browsers (*kuch* IE *kuch*) kunnen terugvallen op een OS lettertype.
  6. Overweeg OS lettertypen: Je weblettertype van 500 kB ziet er misschien prachtig uit, maar zou iemand het verschil merken als je overstapt naar de algemeen beschikbare lettertypen Helvetica, Arial, Georgia of Verdana? OS of web-safe lettertypen zijn een gemakkelijke manier om de prestaties te verbeteren.

Gebruik de juiste optie om het lettertype te laden

Het kan een paar seconden duren voordat weblettertypen zijn gedownload en verwerkt. De browser zal ofwel:

  1. Een Flash of Unstyle Text (FOUT) laten zien: het eerste beschikbare fallback-lettertype wordt als eerst gebruikt, maar wordt vervangen zodra het weblettertype gereed is.
  2. Een Flash of Invisible Text (FOIT) laten zien: er wordt geen tekst weergegeven totdat het weblettertype gereed is. Dit is het standaardproces in moderne browsers, die doorgaans drie seconden wachten voordat ze kiezen voor een fallback-lettertype.

Geen van beide is ideaal. De CSS font-display property en Google Font & display = parameter kan een alternatieve optie selecteren:

  • auto: het standaardgedrag van de browser (meestal FOIT).
  • block: in de praktijk FOIT. Tekst is maximaal drie seconden onzichtbaar. Er is geen lettertypewissel, maar het kan even duren voordat de tekst verschijnt.
  • swap: in de praktijk FOUT. De eerste fallback wordt gebruikt totdat het weblettertype beschikbaar is. Tekst is direct leesbaar, maar het effect van het wisselen van lettertype kan de gebruikerservaring verstoren. Font Style Matcher kan worden gebruikt om een fallback van vergelijkbare grootte te definiëren.
  • fallback: een compromis tussen FOIT en FOUT. De tekst is een korte periode onzichtbaar (meestal 100ms), daarna wordt de eerste fallback gebruikt totdat het weblettertype beschikbaar is.
  • optional: vergelijkbaar met fallback, behalve dat er geen lettertypewisseling plaatsvindt. Het weblettertype wordt alleen gebruikt als het binnen de beginperiode beschikbaar is. Je view van de eerste pagina zal waarschijnlijk een fallback-lettertype laten zien, en daaropvolgende views zullen het gedownloade gecachete weblettertype gebruiken.

Het gebruik van swap, fallback of optional kan een prestatieverbetering bieden.

Vermijd CSS @import

Met @import at-rule kunnen CSS bestanden in andere worden opgenomen:

/* main.css */
@import url("reset.css");
@import url("grid.css");
@import url("widget.css");

Dit lijkt een effectieve manier om kleinere componenten en lettertypen te laden. Helaas is elke @import render-blocking, en moet elk bestand in serie worden geladen en geparset.

Meerdere <link> tags binnen HTML is meer efficiënt en laad CSS bestanden parallel:

<link rel="stylesheet" href="reset.css">
<link rel="stylesheet" href="grid.css">
<link rel="stylesheet" href="widget.css">

Dat gezegd hebbende, dit is een beter idee…

Voeg CSS samen en verklein ze

Moderne build-tools, CSS-preprocessors zoals Sass en WordPress plugins kunnen alle onderdelen combineren in één groot CSS bestand. Onnodige witruimte, opmerkingen en tekens worden vervolgens verwijderd om de bestandsgrootte tot een minimum te beperken.

Meerdere bestanden vormen minder een prestatieprobleem sinds  HTTP/2  en hoger, maar een enkel bestand vereist slechts één header en kan efficiënter worden gegzipt en in de cache worden opgeslagen.

Afzonderlijke CSS bestanden zijn alleen praktisch als je een of meer stylesheets hebt die vaak worden gewijzigd – misschien meerdere keren per week. Zelfs dan kan de meestal statische CSS code nog steeds in één bestand worden gecombineerd.

Klanten van Kinsta hebben toegang tot de codeminificatiefeature in hun MyKinsta dashboard om hiermee te helpen. De feature stelt klanten in staat om automatische CSS en JavaScript minificatie in te schakelen met een simpele klik. Dit helpt bij het versnellen van een site zonder dat je hier iets voor hoeft te doen.

Vermijd Base64 encoding

Tools kunnen afbeeldingen coderen naar base64 strings, die je kan gebruiken als data URI’s in HTML <img> tags en CSS achtergronden:

.background {
  background-image: url('data:image/jpg;base64,ABC123...');
}

Dit vermindert het aantal HTTP verzoeken, maar is nadelig voor de CSS performance:

  • base64 strings kunnen 30% groter zijn dan hun binaire equivalent.
  • browsers moeten de string decoderen voordat een afbeelding kan worden gebruikt, en
  • als je een afbeeldingspixel wijzigt, wordt het hele CSS bestand ongeldig.

Overweeg alleen base64 encoding als je zeer kleine, zelden veranderende afbeeldingen gebruikt waarvan de resulterende string niet aanzienlijk langer is dan een URL.

Dat gezegd hebbende, gebruik gerust UTF8 codering voor herbruikbare SVG pictogrammen, bijv.

.svgbackground {
  background-image: url('data:image/svg+xml;utf8,');
}

Verwijder CSS hacks en IE fallbacks

Tenzij je pech hebt en een groot aantal Internet Explorer gebruikers hebt, kunnen IE conditionele stylesheets en hacks uit je CSS worden verwijderd. In de meeste gevallen zullen IE gebruikers nog steeds iets zien, vooral als je een mobile-first design gebruikt dat standaard een eenvoudiger lineair beeld laat zien. Het resultaat is misschien niet mooi, en het zal niet fantastisch zijn, maar je ontwikkelingsbudget kan beter worden besteed aan de toegankelijkheid voor alle gebruikers.

Preload CSS bestanden

De <link> tag biedt een optioneel preload attribuut waarmee onmiddellijk een download kan worden gestart in plaats van te wachten op de echte verwijzing in de HTML:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>My page</title>
  <!-- preload styles -->
  <link rel="preload" href="/css/main.css" as="style" />
  <!-- lots more code -->
  <!-- load preloaded styles -->
  <link rel="stylesheet" href="/css/main.css" />

Dit is vooral handig in WordPress en andere CMS’en waar een plugin een stylesheet verderop op de pagina kan toevoegen.

Gebruik critical inline CSS

Analysetools kunnen je de suggestie doen dat je ” inline critical CSS”  of ” reduce render-blocking style sheets.” Dit verbetert de prestaties door:

  1. Essentiële stijlen te identificeren die worden gebruikt door above-the-fold elementen (die zichtbaar zijn terwijl de pagina wordt geladen)
  2. Inline die essentiële CSS in een <style> tag in je <head>
  3. De resterende CSS asynchroon te laden om render-blocking te voorkomen. Dit kan je doen door de stylesheet te laden in een “print” stijle die de browser een lage prioriteit geeft. JavaScript schakelt vervolgens over naar een “all” mediastijl zodra de pagina is geladen (een <noscript> zorgt ervoor dat de CSS werkt als de JavaScript niet beschikbaar is):
<style>
/* critical styles */
body { font-family: sans-serif; color: #111; }
</style>
<!-- load remaining styles -->
<link rel="stylesheet" 
     href="/css/main.css"
    media="print" 
   onload="this.media='all'">
<noscript>
  <link rel="stylesheet" href="/css/main.css">
</noscript>

Tools zoals critical en criticalCSS kunnen helpen bij het extracten van stijlen voor in-view elementen.

Deze techniek verbetert merkbaar de prestaties en verhoogt de auditscores. Sites of apps met consistente interfaces zouden eenvoudiger te implementeren moeten zijn, maar in andere scenario’s kan het lastiger zijn:

  • Een build-tool is essentieel voor alle sites, behalve de eenvoudigste sites.
  • De “fold” is op elk apparaat anders.
  • Sites kunnen verschillende layouts hebben die allemaal hun eigen kritieke CSS hebben.
  • CSS tools die met kritieke CSS werken kunnen moeite hebben met specifieke frameworks, client-side gegenereerde HTML en dynamische content.
  • Vooral het laden van de eerste pagina kan profiteren van de techniek. CSS wordt gecachet voor de volgende pagina’s, dus extra inline-stijlen zullen het paginagewicht vergroten.

Gebruik rendering van media query’s

Een enkel samengevoegd en geminificeerd bestand zal de meeste sites ten goede komen, maar sites die een aanzienlijk aantal stijlen voor grote schermen bevatten, kunnen de CSS bestanden vaak beter splitsen en laden met behulp van een media query:

<!-- core styles loaded on all devices -->
<link rel="stylesheet" href="core.css">
<!-- served to screens at least 40em wide -->
<link rel="stylesheet" media="(min-width: 40em)" href="40em.css">
<!-- served to screens at least 80em wide -->
<link rel="stylesheet" media="(min-width: 80em)" href="80em.css">

Dit voorbeeld volgt de mobile-first methodologie. Mobiele apparaten laden core.css maar hoeven de overige stylesheets mogelijk niet te downloaden of te parsen.

Gebruik progressieve rendering

Progressieve rendering is een techniek die individuele stylesheets definieert voor afzonderlijke pagina’s of componenten. Het is zeer geschikt voor grote sites waar individuele pagina’s zijn opgebouwd uit een uitgebreide reeks componenten.

Elk CSS bestand wordt onmiddellijk geladen voordat er in de HTML naar een component wordt verwezen.

<head>
  <!-- core styles -->
  <link rel="stylesheet" href="core.css" />
</head>
<body>
  <!-- header -->
  <link rel="stylesheet" href="header.css" />
  <header>...</header>
  <!-- primary content -->
  <link rel="stylesheet" href="main.css" />
  <main>
    <!-- widget styling -->
    <link rel="stylesheet" href="widget.css" />
    <div class="mywidget>...</div>
  </main>
  <!-- footer -->
  <link rel="stylesheet" href="footer.css" />
  <footer>...</footer>
</body>

Dit werkt goed in de meeste browsers. (Safari toont een lege pagina totdat alle CSS is geladen, maar het zou niet merkbaar slechter moeten zijn dan een enkele grote stylesheet.)

Door Web Components te gebruiken, wordt ook het gebruik van scoped stijlen aangemoedigd die worden geladen wanneer het aangepaste element wordt weergegeven.

CSS prestaties optimaliseren

Verschillende CSS technieken en eigenschappen leggen op verschillende manieren druk op de browser, CPU, geheugen, bandbreedte en andere resources. De volgende tips kunnen je helpen onnodige verwerking en trage prestaties te voorkomen.

Gebruik moderne layouttechnieken (grid en flexbox)

Float-based layouts zijn moeilijk te maken, gebruiken talloze properties, vereisen voortdurende aanpassingen voor de marges en paddings, moeten worden beheerd met media queries en de verwerking ervan trekt zwaar op de browser. Ze waren in de praktijk jarenlang de enige mogelijke layoutmethode, maar ze zijn niet langer nodig. Gebruik ofwel:

  • CSS Flexbox voor eendimensionale layouts die door kunnen lopen naar de volgende rij. Het is ideaal voor menu’s, afbeeldingengalerijen, kaarten, etc.
  • CSS Grid voor tweedimensionale layouts met expliciete rijen en kolommen. Het is ideaal voor paginalayouts.

Beide zijn eenvoudiger te ontwikkelen, gebruiken minder code, worden sneller weergegeven en passen zich aan elk schermformaat aan zonder media query’s.

Erg oude browsers herkennen moderne flexbox- en rasterproperties niet, elk element wordt in dat geval een blok. Toon ze in een eenvoudige, mobielachtige lineaire layout: het is niet nodig om het ontwerp na te bootsen met op float gebaseerde fallbacks.

Vervang afbeeldingen met CSS gradients en effecten

Kies waar mogelijk voor CSS code in plaats van afbeeldingen. Experimenteer met gradients, randen, straal, schaduwen, filters, blend modes, masks, clipping en pseudo-element effecten om bestaande afbeeldingen opnieuw te gebruiken of te vervangen.

CSS-effecten gebruiken aanzienlijk minder bandbreedte, zijn gemakkelijker aan te passen en kunnen meestal worden geanimeerd.

Vermijd overmatig gebruik van dure properties

Je gebruikt misschien beknopte declaratieve code, maar sommige CSS vereist meer verwerking dan andere. De volgende properties triggeren painting-berekeningen die bij overmatig gebruik ” duur” kunnen uitvallen:

  • position: fixed
  • border-radius
  • box-shadow
  • text-shadow
  • opacity
  • transform
  • filter
  • backdrop-filter
  • background-blend-mode

Gebruik waar mogelijk CSS overgangen en animaties

CSS overgangen en animaties zullen altijd vloeiender zijn dan door JavaScript aangedreven effecten die vergelijkbare eigenschappen wijzigen. In zeer oude browsers worden ze niet verwerkt, maar omdat deze waarschijnlijk op minder capabele apparaten worden uitgevoerd, is dat helemaal geen probleem.

Vermijd echter overmatige animatie. Effecten moeten de gebruikerservaring verbeteren zonder de prestaties nadelig te beïnvloeden of misselijkheid te veroorzaken. Check de prefers-reduced-motion media query en schakel animaties uit indien nodig.

Vermijd het animeren van properties die een re-layout triggeren

Het wijzigen van de afmetingen van een element (breedte, hoogte, opvulling, rand) of de positie (boven, onder, links, rechts, marge) kan ertoe leiden dat de hele pagina op elk animatieframe opnieuw moet worden ingedeeld. De meest efficiënte properties om te animeren zijn:

  • opacity
  • filter: blur, contrast, schaduw en andere effecten
  • transform: een element translaten (verplaatsen), schalen of roteren

Browsers kunnen de hardware-versnelde GPU gebruiken om deze effecten in hun eigen laag weer te geven, zodat alleen de composition-fase wordt beïnvloed.

Als je andere properties moet animeren, kan je de prestaties verbeteren door het element uit de paginaflow te halen met position: absolute.

Kijk uit met complexe selectors

Browsers zullen vaak snel de meest complexe CSS selectors parsen, maar door ze te vereenvoudigen, worden de bestandsgroottes kleiner en worden de prestaties verbeterd. Complexe selectors worden vaak gegenereerd wanneer je zeer geneste structuren maakt in CSS preprocessors zoals Sass.

Geef aan welke elementen zullen veranderen

Met de CSS will-change property kan je waarschuwen hoe een element wordt gewijzigd of geanimeerd, zodat de browser van tevoren optimalisaties kan uitvoeren:

.myelement {
  will-change: transform, opacity;
}

Er kan een willekeurig aantal door komma’s gescheiden waarden worden gedefinieerd, maar de eigenschap mag alleen worden gebruikt als laatste redmiddel om bekende prestatieproblemen op te lossen. Je moet het niet op te veel elementen toepassen, en zorg ervoor dat je het voldoende tijd geeft om te initialiseren.

Overweeg CSS containment

Containment is een nieuwe CSS feature die de prestaties kan verbeteren doordat je geïsoleerde substructuren van een pagina kunt identificeren. De browser kan de verwerking optimaliseren door een specifiek DOM contentblok wel of niet te renderen.

De contain property accepteert een of meer van de volgende waarden in een door spaties gescheiden lijst:

  • none: containment wordt niet toegepast
  • layout: de layout van het element is geïsoleerd van de rest van de pagina — de content heeft geen invloed op andere elementen
  • paint: children van het element worden niet buiten de grens weergegeven
  • size: de grootte van het element kan worden bepaald zonder child-elementen te controleren — de afmetingen zijn onafhankelijk van de inhoud

Er zijn ook twee speciale waarden beschikbaar:

  • strict: Alle containment regels (behalve none) worden toegepast
  • content: past layout en paint toe

CSS containment wordt ondersteund door de meeste moderne browsers. Er is geen ondersteuning in Safari of oudere applicaties, maar containment kan toch veilig worden gebruikt omdat dergelijke browsers de property simpelweg negeren.

Reageer op de Save-Data header

Save-Data is een HTTP requestheader die aangeeft dat de gebruiker om minder gegevens heeft gevraagd. In sommige browsers heet dit “Lite” of “Turbo” modus.

Indien ingeschakeld, wordt bij elk browserverzoek een Save-Data header verzonden:

GET /main.css HTTP/1.0
Host: site.com
Save-Data: on

De server kan dienovereenkomstig reageren wanneer Save-Data wordt gedetecteerd. In het geval van CSS kan het een eenvoudiger mobielachtige lineaire layout verzenden, een OS lettertype gebruiken, overschakelen naar blokkleuren of afbeeldingsachtergronden met een lage resolutie laden.

Merk op dat de server de volgende header moet retourneren bij gewijzigde verzoeken om ervoor te zorgen dat minimale content niet in de cache wordt opgeslagen en opnieuw wordt gebruikt wanneer de gebruiker de Lite/Turbo modus uitschakelt:

Vary: Accept-Encoding, Save-Data

De header kan ook worden gedetecteerd door JavaScript aan de clientzijde. De volgende code voegt een bestUX klasse toe aan het <html> element wanneer Save-Data niet is ingeschakeld:

if ('connection' in navigator && !navigator.connection.saveData) {
  document.documentElement.classList.add('bestUX');
}

Stylesheets kunnen dan dienovereenkomstig reageren zonder enige servermanipulatie:

/* no hero image by default */
header {
  background-color: #abc;
  background-image: none;
}
/* hero image when no Save-Data */
.bestUX header {
  background-image: url("hero.jpg");
}

De prefers-reduced-data media query biedt een CSS-only optie als alternatief, hoewel dit op het moment van schrijven door geen enkele browser wordt ondersteund:

/* no hero image by default */
header {
  background-color: #abc;
  background-image: none;
}
/* hero image when no Save-Data */
@media (prefers-reduced-data: no-preference) {
  header {
    background-image: url("hero.jpg");
  }
}

Samenvatting

Er zijn veel opties om de CSS prestaties te optimaliseren, maar overweeg voor nieuwe projecten de volgende praktijken:

  1. Gebruik een mobile-first benadering: Codeer eerst de eenvoudigste mobiele layout en voeg vervolgens verbeteringen toe voor grotere schermen en complexere browsers.
  2. Splits CSS op in afzonderlijke bestanden met identificeerbare verantwoordelijkheden: Een CSS pre-processor of CMS plugin kan CSS partials combineren in een enkel bestand.
  3. Voeg een bouwstap toe: Er zijn tools beschikbaar die automatisch coderen, problemen identificeren, samenvoegen, minificeren en afbeeldingsgroottes verkleinen en meer. Automatisering maakt het leven gemakkelijker en je vergeet minder snel een optimalisatiestap.
  4. Documenteer je stylesheets: een stijlgids met gedocumenteerde voorbeelden maakt het gemakkelijker om te werken met je code en deze te onderhouden. Je kan zonder problemen oude CSS identificeren en verwijderen.

Ten slotte: leer CSS! Hoe meer je weet, hoe minder code je hoeft te schrijven en hoe sneller je webtoepassing wordt. Het maakt je een betere ontwikkelaar, ongeacht de platforms en frameworks die je gebruikt.

Welke andere tips heb je voor het optimaliseren van CSS prestaties? Deel ze in de reacties hieronder!

Craig Buckler

Freelance UK web developer, writer, and speaker. Has been around a long time and rants about standards and performance.