Critical

Critical CSS

Von am 07.12.2015

Angefangen hat alles mit Google PageSpeed Insights. Als Ben Edwards seine Website mit dem Tool von Google überprüfte, empfahl es ihm Teile von seinem CSS-Code inline im HTML-Dokument auszuliefern um die Ladezeit zu verkürzen. CSS Code in HTML einbinden, hört sich im ersten Moment schrecklich und falsch an. Gerade für mobile Geräte, wo die Internetverbindung nicht immer optimal ist (z. B. U-Bahn) ist eine Verbesserung der Ladezeit gewünscht. Da kann Critical CSS hilfreich sein.

Was Google PageSpeed aber damit sagen will ist, dass externe CSS-Dateien (eingebunden via `<link>`) das Rendern der Seite im Browser blockieren. Das heißt, dass das Rendern erst fortgesetzt wird, wenn die Dateien geladen sind. Was auch logisch ist, die Informationen müssen ja erst heruntergeladen werden, was durch Latenz und Dateigröße zu Verzögerungen führen kann. Die Empfehlung ist daher den CSS-Code aufzuteilen: Ein Teil inline, den Rest wie üblich in der CSS Datei.

Der Inline-Teil (also direkt im `<head>` durch `<style>`) soll alles beinhalten, was zum rendern des Sichtbereichs („above-the-fold“, der Begriff kommt von Zeitungen, wenn diese gefaltet sind, ist nur der obere Bereich der Zeitung sichtbar) notwendig is. Dieser Teil wird als „critical“ bezeichnet. Der Begriff „critical“ kommt von Ben Edwards, der diese Teile im CSS mit „critical“ angegeben hat.

Welcher Code ist kritisch?

Hört sich im Prinzip einfach an, aber wie kommt man jetzt an den Code der benötigt wird? Man könnte schon während der Erstellung darauf achten und diesen dann manuell kopieren. Das Ganze natürlich für die mobile und Desktop Ansicht ermittelt werden.

Es gibt dazu ein paar nützliche Tools:

Wenn der kritische Teil des CSS eingebunden ist, kann auch noch zusätzlich der restliche Teil asynchron geladen werden, z. B. mit loadCSS.

Automatisierung

Schöner wäre es allerdings, das ganze zu automatisieren. Dazu kann man z. B. das Build System Gulp verwenden. Auf der Github-Seite von Addy Osmani gibt es dazu ein umfassendes Tutorial. Der Workflow mit Grunt wird im NPM Critical Package beschrieben.

Der Ablauf für den Task ist wie folgt:

  • Stylesheet-Dateien vom Quellverzeichnis in das Build-Verzeichnis kopieren.
    Notwendig für Fallback, falls kein JS aktiviert.
  • HTML-Datei einlesen und critical CSS ermitteln (dazu können Parameter wie Breite und Höhe angegeben werden).

Das wars auch schon. Vorher sollte man in der HTML-Datei die `<link>`-Tags mit den CSS-Dateien annotieren, die man zu einer Datei zusammenfassen will. Die kritischen CSS-Regeln werden automatisch eigebunden. Außerdem ein Script (loadCSS), das sich um das asynchrone Nachladen der CSS-Dateien kümmert.

Nachteil: Die CSS-Dateien werden nicht geändert, d. h. die Regeln werden doppelt ausgeliefert, da mit dem Package die kritischen Regeln so gut wie möglich zusammengefasst werden. Hier besteht sicher noch Optimierungsbedarf des Packages. Dies kann z. B. mit CSS-Preprozessoren umgangen werden, indem man seine Dateien aufteilt und sich selbst um den Above-the-Fold-Code kümmert (also wieder manuell).

Ich habe das auch mit Gulp und der MFG-Website getestet, was auch ohne Probleme funktioniert hat. Da die MFG-Website aber ohnehin recht schnell lädt, konnte ich keinen Unterschied feststellen. Was lange gedauert hat zu laden, waren die Schriften (Stichwort: „FOIT“).

gulp.task('critical', function() {
    critical.generateInline({
        // Verzeichnis mit den Quelldateien
        base: 'src/',
        // HTML-Datei im Quellverzeichnis
        src: 'index.html',
        // Datei die das kritische CSS enthalten soll
        styleTarget: 'dist/critical.css',
        // Neue HTML-Datei mit kritischem CSS und &quot;loadCSS&quot;
        htmlTarget: 'dist/index.html',
        // Breite die abgesucht wird
        width: 320,
        // Höhe die abgesucht wird
        height: 480,
        // Minify
        minify: true
    });
});

Fazit

Auf kritisches CSS zu achten, ist zeitaufwendig, kann sich aber bezahlt machen. User sind schnell wieder weg, wenn sie das Gefühl haben, zu lange auf die Seite warten zu müssen. Und gerade bei mobilen Geräten verschafft es einen zusätzlichen Schub. Ob sich der Aufwand lohnt (vielleicht lässt sich die Seite auch in anderen Punkte optimieren? Vielleicht muss ich gar nicht so viele Ressourcen ausliefern?) muss jeder für sich entscheiden.
Wer HTTP/2 einsetzt, könnte auf solche Maßnahmen verzichten, denn damit lassen sich mehrere Requests mit einer Verbindung verarbeiten (Multiplexing) und Ressourcen können sich nicht mehr gegenseitig blockieren. Bis HTTP/2 aber allgegenwärtig ist dauert es sicher noch einige Jahre.

Zusätzliche Links & Quellen

The comments are closed.