Das Wichtigste in 30 Sekunden

  • Render-blockierende Ressourcen zwingen den Browser, mit dem Zeichnen der Seite zu warten, bis CSS und JavaScript vollständig geladen und verarbeitet sind.
  • Kritisches CSS gehört als minimierter <style>-Block in den <head>, der Rest lädt asynchron nach.
  • defer und async bedeuten nicht dasselbe: defer erhält die Ausführungsreihenfolge, async nicht. Die Wahl hängt davon ab, ob ein Skript Abhängigkeiten hat.
  • Web-Fonts und Third-Party-Scripts sind häufig unterschätzte Render-Blocker, die sich mit font-display: swap und rel="preconnect" entschärfen lassen.

Was render-blocking bedeutet und warum der Browser wartet

Öffnen Sie in Chrome die Entwicklertools, wechseln Sie zum Tab „Performance“ und zeichnen Sie einen Seitenaufruf auf. Im Wasserfall-Diagramm sehen Sie, wie einige Ressourcen alles andere aufhalten: Sie liegen auf dem kritischen Pfad, bevor das erste Pixel gezeichnet werden kann. Diese Ressourcen heißen render-blocking.

Kurz gesagt: Render-blockierende Ressourcen sind Stylesheets und Skripte, die der Browser vollständig herunterladen und verarbeiten muss, bevor er den sichtbaren Bereich der Seite überhaupt zeichnet. Jede Zehntelsekunde, die dabei vergeht, verzögert den Largest Contentful Paint (LCP) direkt.

Der Mechanismus dahinter ist im Browser fest verdrahtet. Wenn der HTML-Parser auf <link rel="stylesheet"> trifft, hält er an, bis die CSS-Datei heruntergeladen und das CSSOM (CSS Object Model) vollständig aufgebaut ist. Der Grund ist nachvollziehbar: Der Browser muss wissen, welche Stile für jedes Element gelten, bevor er den Render-Tree berechnen und anschließend auf dem Bildschirm zeichnen kann. Rendern ohne vollständiges CSS würde bedeuten, alles danach sofort wieder verwerfen zu müssen.

Für JavaScript gilt ein verwandtes, aber etwas anderes Prinzip. Ein <script>-Tag ohne defer oder async im <head> blockiert das Parsing komplett, weil das Skript theoretisch das DOM oder den Stil der noch nicht gerenderten Seite verändern könnte. Der Browser geht auf Nummer sicher und wartet. Lighthouse markiert genau diese zwei Fälle als render-blocking: Scripts im <head> ohne defer/async und Stylesheets ohne spezifisches media-Attribut.

Das Problem ist nicht der Mechanismus selbst, sondern sein Ausmaß in der Praxis. Ein WordPress-Theme liefert oft mehrere hundert Kilobyte CSS aus, von denen beim ersten Laden vielleicht fünf Prozent für den sichtbaren Bereich gebraucht werden. Die übrigen 95 Prozent blockieren trotzdem. Laut dem Artikel zu den häufigsten Performance-Ursachen ist genau das einer der am weitesten verbreiteten Ladezeit-Killer auf mittelständischen Websites.

CSS: Kritisches inline ausliefern, den Rest asynchron nachladen

Kurz gesagt: Kritisches CSS sind die Stile, die für den sichtbaren Bereich ohne Scrollen gebraucht werden. Diese kommen als <style>-Block in den <head>, typischerweise 10–20 KB minimiert. Alles andere lädt asynchron per media="print"-Trick oder rel="preload".

Die Extraktion des kritischen CSS ist der wirksamste einzelne Schritt gegen render-blockierende Stylesheets. Tools wie Critical oder PurgeCSS können dabei helfen, manuell ist es der Coverage-Tab in den Chrome DevTools: Seite laden, Tab öffnen, Reload starten. Die roten Balken zeigen, welche CSS-Regeln beim ersten Laden nicht gebraucht wurden.

Für das asynchrone Nachladen des vollen Stylesheets gibt es zwei verbreitete Methoden. Die erste nutzt einen Umweg über das Druckmedia-Attribut, weil der Browser CSS für den Druck nicht als darstellungskritisch einstuft:

<link rel="stylesheet" href="styles.css" media="print"
      onload="this.media='all'; this.onload=null;">
<noscript><link rel="stylesheet" href="styles.css"></noscript>

Die zweite Methode aus dem web.dev-Leitfaden zu nicht-kritischem CSS nutzt rel="preload" mit dem as="style"-Attribut:

<link rel="preload" href="styles.css" as="style"
      onload="this.onload=null; this.rel='stylesheet';">
<noscript><link rel="stylesheet" href="styles.css"></noscript>

Beide Varianten benötigen die <noscript>-Zeile als Fallback, damit die Seite auch ohne JavaScript korrekt gestylt bleibt. Das this.onload=null verhindert, dass der Handler in manchen Browsern in einer Endlosschleife landet. Wer ohne Inline-JavaScript auskommen muss, weil eine Content Security Policy das verbietet, greift auf die Bibliothek loadCSS zurück, die dieses Verhalten CSP-kompatibel kapselt.

Wichtig: Das Caching eines inline ausgelieferten kritischen CSS funktioniert anders als bei externen Stylesheets. Das kritische CSS ist im HTML-Dokument eingebettet und wird mit ihm gecacht, nicht separat. Das ist bei kleinen Stylesheets kein Problem, bei größeren kann es die HTML-Größe spürbar erhöhen.

JavaScript: defer vs. async

Hier liegt die häufigste Verwechslung beim Auflösen von render-blocking: defer und async bedeuten nicht dasselbe. Die Unterschiede sind klein, aber die Konsequenzen bei falscher Wahl sind es nicht.

Kurz gesagt: defer lädt parallel zum HTML-Parsing, führt aber erst nach abgeschlossenem Parsing aus, in Dokumentreihenfolge. async lädt ebenfalls parallel, führt aber sofort nach dem Download aus, ohne Reihenfolgegarantie. Beide Attribute haben keine Wirkung auf Inline-Skripte.

Was MDN zur defer-Spezifikation beschreibt: Das Skript wird parallel zum Parsing heruntergeladen, die Ausführung startet erst nachdem das vollständige Dokument geparst ist, aber noch vor dem DOMContentLoaded-Event. Mehrere defer-Skripte werden in der Reihenfolge ausgeführt, in der sie im Dokument stehen.

Für async gilt: Download parallel zum Parsing, Ausführung sofort nach dem Download, unabhängig davon, wo der Parser gerade steht. Lädt Skript B schneller herunter als Skript A, das im Dokument vor B steht, wird B zuerst ausgeführt. Hängt B von A ab, führt das zu Fehlern.

Die Praxisregel ist einfach: Alles, das den DOM braucht oder andere Skripte voraussetzt (jQuery, Slider, Formularlibrarys, WordPress-Plugin-Scripts), bekommt defer. Nur vollständig isolierte, abhängigkeitsfreie Skripte kommen für async infrage, zum Beispiel ein eigenständiges Analytics-Tag oder ein externes Chat-Widget ohne DOM-Interaktion.

Wichtig ist auch, was beide Attribute nicht können: Inline-Skripte, also Code direkt zwischen <script>-Tags ohne src-Attribut, werden von weder defer noch async beeinflusst. Die Attribute funktionieren ausschließlich bei externen Skripten mit src-Attribut. Wer Inline-Skripte aus dem blocking-Pfad herausnehmen will, muss sie entweder in externe Dateien auslagern oder ans Ende des <body> verschieben.

In WordPress lassen sich Scripts per wp_script_add_data() auf defer oder async umstellen. Alternativ prüfen viele Performance-Plugins die gesamte Skript-Queue. Welche Skripte auf einer Seite aktiv sind und welchen Anteil davon ungenutzt bleibt, zeigt der Coverage-Tab in Chrome DevTools. Das ist der sinnvolle Startpunkt vor jedem Eingriff.

Third-Party-Scripts unter Kontrolle

Google Tag Manager, Facebook Pixel, Chat-Widgets, Consent-Manager: Diese Scripts kommen von fremden Domains, und jede fremde Domain kostet Zeit. Vor dem ersten Byte muss der Browser einen DNS-Lookup, den TCP-Verbindungsaufbau und den TLS-Handshake für diese Origin abschließen. Wie web.dev beschreibt, kann dieser Verbindungsaufbau zu fremden Origins gerade in langsamen Netzen spürbar Zeit kosten. Als grobe Faustregel kann man je nach Netz und Serverstandort mit etwa 100 bis 300 Millisekunden pro neuer Origin rechnen.

Kurz gesagt: rel="preconnect" baut die Verbindung zu einer fremden Domain vor, sobald der Browser den <head> verarbeitet. Das spart den Verbindungsaufbau, wenn das eigentliche Skript dann angefordert wird. rel="dns-prefetch" ist der sparsamere Bruder: nur DNS, kein TLS.
<link rel="preconnect" href="https://fonts.googleapis.com" crossorigin>
<link rel="dns-prefetch" href="https://www.googletagmanager.com">

preconnect ist ressourcenintensiver, weil es eine vollständige Verbindung inkl. TLS aufbaut. Sinnvoll ist es nur für Origins, deren Ressourcen der Browser mit hoher Wahrscheinlichkeit auf der aktuellen Seite lädt. Für Origins, die erst auf bestimmten Unterseiten aktiv sind, reicht dns-prefetch.

Was aber wirklicher hilft als alle Hints zusammen: Third-Party-Scripts kritisch hinterfragen. Jedes Script, das nicht zwingend benötigt wird, ist besser nicht eingebunden. Der Google Tag Manager vereinfacht das Hinzufügen von Scripts, ersetzt aber nicht die Pflege. In der Praxis finden wir auf Mittelstandsseiten regelmäßig Scripts im Tag Manager, deren Kampagnen seit Jahren beendet sind.

Für Scripts, die definitiv geladen werden müssen, aber nicht sofort gebraucht werden, bietet async in Kombination mit einer Script-Strategie wie „load after user interaction“ eine deutliche Entlastung. Das Consent-Management-Tool lädt dabei erst, wenn der Nutzer die Seite berührt oder scrollt, nicht beim ersten Byte des Dokuments.

Web-Fonts: der stille Render-Blocker

Web-Fonts werden in der Lighthouse-Auswertung seltener als render-blocking gelistet, weil sie technisch nicht den ersten Paint blockieren. Trotzdem verursachen sie ein eng verwandtes Problem: FOIT und FOUT. Ohne Instruktion wartet der Browser standardmäßig bis zu drei Sekunden, bevor er Text mit einer Fallback-Schrift anzeigt. In dieser Zeit sieht der Nutzer leere Textbereiche statt des Inhalts. Das drückt den LCP genauso wie ein echter Render-Blocker.

Kurz gesagt: font-display: swap in der @font-face-Regel zeigt sofort die Fallback-Schrift an und tauscht auf die Web-Font, sobald sie geladen ist. Für Fonts, die lokal liegen, entfällt der externe Verbindungsaufbau komplett.

Die empfohlene Kombination für lokal gehostete Fonts: font-display: swap in der CSS-Regel plus <link rel="preload"> für die WOFF2-Datei im <head>. Das preload teilt dem Browser mit, die Fontdatei mit hoher Priorität zu laden, bevor er das CSS-Request für die Schriftdatei im normalen Dokumentfluss stellt.

<link rel="preload" href="/fonts/inter.woff2" as="font"
      type="font/woff2" crossorigin>

Das crossorigin-Attribut ist dabei kein optionales Detail: Ohne es wird die Fontdatei vom Browser zweimal angefordert, weil Fonts grundsätzlich als CORS-Anfragen behandelt werden. Das hat die web.dev-Dokumentation zu preload explizit als häufigen Fehler notiert. Ob crossorigin sitzt oder nicht, ist im Netzwerk-Tab der DevTools sofort sichtbar: zwei Einträge für dieselbe Fontdatei zeigen den Fehler.

Google Fonts extern einzubinden ist aus zwei Gründen keine gute Wahl. Erstens baut der Browser eine neue TLS-Verbindung zu fonts.googleapis.com und fonts.gstatic.com auf. Zweitens überträgt der Browser dabei die IP-Adresse des Nutzers an Google-Server, was mehrere deutsche Gerichte als datenschutzrechtlich unzulässig eingestuft haben (u. a. LG München I, Az. 3 O 17493/20, 20.01.2022). Schriften lokal zu hosten ist schneller und rechtlich sauber. Das belegte Vorgehen steht im Artikel zu langsamen Websites im Detail.

Übersicht: Ressource, Problem und Lösung

Ressource Problem Lösung
Externes CSS Blockiert ersten Paint komplett bis Download + CSSOM-Aufbau Critical CSS inline im <head>, Rest per media="print"-Trick oder rel="preload" as="style" asynchron
Ungenutztes CSS Erhöht Dateigröße und damit Blockierzeit ohne Nutzen Coverage-Tab analysieren, PurgeCSS oder manuelles Bereinigen
Script ohne defer/async Blockiert HTML-Parsing und Rendering bis Ausführung fertig defer bei DOM-abhängigen Scripts, async nur bei isolierten Scripts
Inline-Script im <head> defer/async wirkungslos, blockiert synchron In externe Datei auslagern + defer, oder ans Body-Ende verschieben
Third-Party-Script DNS + TCP + TLS zu fremder Domain pro Origin, 100–300 ms rel="preconnect" für kritische Origins, dns-prefetch für optionale, überflüssige Scripts entfernen
Web-Font extern Verbindungsaufbau zu fremder Domain, FOIT bis zu 3 Sek. Lokal hosten, font-display: swap, rel="preload" mit crossorigin
LCP-Bild spät entdeckt Browser findet Bild-URL erst spät im Parsing, LCP verzögert rel="preload" as="image" + fetchpriority="high" im <head>

Code-Beispiele: defer, async und preload im Vergleich

Die folgenden Beispiele zeigen die drei gängigsten Muster und wann welches passt.

<!-- defer: lädt parallel, führt nach dem Parsing aus, Reihenfolge erhalten -->
<!-- Richtig für: jQuery, Slider, Formular-Scripts, alle abhängigen Scripts -->
<script src="jquery.min.js" defer></script>
<script src="main.js" defer></script>

<!-- async: lädt parallel, führt sofort nach Download aus, keine Reihenfolge -->
<!-- Richtig für: isolierte Analytics-Tags ohne DOM-Abhängigkeit -->
<script src="analytics.js" async></script>

<!-- preload: lädt früh mit hoher Priorität, führt nicht aus -->
<!-- Richtig für: LCP-Bild, kritische Schriftdatei, spät im Dokument referenziertes Script -->
<link rel="preload" href="/fonts/inter.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="hero.jpg" as="image" fetchpriority="high">
<link rel="preload" href="app.js" as="script">

Was dabei nicht funktioniert: defer oder async bei einem Script ohne src-Attribut. Das ist ein häufiger Fehler bei WordPress-Sites, wo Theme-Code direkt als Inline-Block im <head> landet. Diese Blöcke ignorieren beide Attribute vollständig.

Das Attribut fetchpriority ist eine neuere Ergänzung: Chrome unterstützt es seit Version 102, Safari seit Version 17.2. Ältere Browser ignorieren es ohne Fehler, es ist also gefahrlos als progressive Verbesserung einsetzbar. Mit fetchpriority="high" signalisiert man dem Browser, dass das LCP-Bild Vorrang vor anderen Ressourcen ähnlicher Priorität hat.

Schritt für Schritt: render-blocking auflösen

  1. Messen und Ausgangspunkt bestimmen. PageSpeed Insights für die URL aufrufen, den Abschnitt „Render-blockierende Ressourcen beseitigen“ öffnen. Alle gelisteten Dateien notieren. Danach Chrome DevTools öffnen, Coverage-Tab aufrufen, Seite neu laden. Rot markierte Anteile zeigen ungenutzten Code.
  2. Kritisches CSS extrahieren. Aus dem Coverage-Bericht oder mit einem Tool wie Critical die Stile herausfiltern, die für den sichtbaren Bereich über der Falz gebraucht werden. Den CSS-Block minimieren (Whitespace, Kommentare entfernen) und als <style>-Block in den <head> einbetten.
  3. Vollständiges Stylesheet asynchron nachladen. Das externe Stylesheet mit dem media="print"-Muster oder rel="preload" as="style" aus dem blockierenden Pfad nehmen. <noscript>-Fallback nicht vergessen.
  4. JavaScript prüfen und defer/async vergeben. Jeden <script>-Tag im <head> anschauen. Hat er defer oder async? Hat er ein src-Attribut? Scripts ohne src entweder auslagern oder nach unten verschieben. Scripts mit DOM-Abhängigkeiten bekommen defer, isolierte Analytics-Tags bekommen async.
  5. Third-Party-Scripts inventarisieren. Alle geladenen externen Origins in den DevTools unter „Network“ einsehen. Für die wichtigsten einen rel="preconnect"-Hinweis setzen. Scripts, die auf keiner Seite mehr gebraucht werden, deaktivieren oder entfernen.
  6. Web-Fonts lokal hosten und preloaden. Fontdateien herunterladen, lokal einbinden, font-display: swap in der @font-face-Regel setzen. rel="preload" mit crossorigin-Attribut für WOFF2-Dateien im <head> ergänzen.
  7. Messen und vergleichen. PageSpeed Insights erneut aufrufen und die Werte mit dem Ausgangsmesswert vergleichen. Im Performance-Tab die Timeline prüfen: Wann beginnt das erste Painting? Der LCP-Marker zeigt, ob die Maßnahmen gewirkt haben.

Praxisbeispiel: Was eine Analyse aufdeckt

Ein typischer Fall aus der Projektarbeit: Eine Unternehmensseite auf WordPress mit einem Theme aus dem Jahr 2021, nicht wesentlich aktualisiert. PageSpeed Insights auf Mobil zeigt LCP 4,8 Sekunden, drei Stylesheet-Einträge und zwei Script-Einträge unter „Render-blockierende Ressourcen“. Das Coverage-Tool zeigt 78 Prozent ungenutztes CSS in der Haupt-Theme-Datei.

Schritt eins: Das Theme-Stylesheet asynchron nachladen und ein kritisches CSS von 14 KB inline setzen. Ergebnis: LCP fällt auf 3,2 Sekunden. Schritt zwei: Zwei Plugin-Scripts bekommen defer, ein Tracking-Pixel bekommt async. Ergebnis: 2,9 Sekunden. Schritt drei: Google Fonts werden lokal gehostet, font-display: swap wird gesetzt, rel="preload" für die WOFF2-Datei ergänzt. Ergebnis: 2,4 Sekunden, damit unter der Google-Schwelle von 2,5 Sekunden.

Was dabei auffiel: Ein Chat-Widget war auf jeder Seite eingebunden, obwohl es nur auf der Kontaktseite sinnvoll war. Das Script allein verursachte durch DNS-Lookup und Verbindungsaufbau zu einer fremden Domain eine messbare Verzögerung auf jeder anderen Seite. Nach dem Entfernen von neun von zehn Seiten fiel der LCP nochmals um 0,2 Sekunden.

Die Kombination aus kritischem CSS, defer/async für Scripts und lokalem Font-Hosting bringt in der Regel den größten Teil der Verbesserung. Wer wissen will, wo die eigene Website steht, bekommt mit dem Core-Web-Vitals-Ratgeber den passenden Kontext und mit dem Website-Check von ihp media eine strukturierte Analyse mit konkreten Prioritäten.

Bei WooCommerce-Shops kommen dieselben Maßnahmen zum Tragen, allerdings mit zusätzlichem Augenmerk auf Plugin-Scripts im Checkout. Der Artikel WooCommerce beschleunigen behandelt die spezifischen Hebel dort im Detail.

Sofort-Checkliste

  • PageSpeed Insights aufgerufen, alle render-blocking Ressourcen notiert?
  • Coverage-Tab in Chrome DevTools: ungenutztes CSS identifiziert?
  • Kritisches CSS als minimierter <style>-Block im <head>?
  • Vollständiges Stylesheet asynchron nachgeladen (media="print"-Trick oder rel="preload" as="style")?
  • <noscript>-Fallback für asynchrones CSS vorhanden?
  • Alle Scripts im <head> haben defer oder async?
  • Scripts mit DOM-Abhängigkeiten haben defer, nicht async?
  • Inline-Scripts ohne src: ausgelagert oder ans Body-Ende verschoben?
  • Third-Party-Origins: rel="preconnect" für kritische, dns-prefetch für optionale gesetzt?
  • Nicht mehr benötigte Third-Party-Scripts deaktiviert oder entfernt?
  • Web-Fonts lokal gehostet, nicht von Google Fonts extern geladen?
  • font-display: swap in der @font-face-Regel gesetzt?
  • rel="preload" für WOFF2-Dateien mit crossorigin-Attribut im <head>?
  • LCP-Bild mit rel="preload" as="image" und fetchpriority="high" vorgeladen?
  • Nach allen Maßnahmen erneut gemessen und LCP mit Ausgangswert verglichen?
Direkt umsetzbar: defer per Filter auf alle WordPress-Scripts

Das folgende Snippet für eine mu-plugins-Datei setzt defer automatisch auf alle enqueued Scripts, lässt dabei jQuery und migrate aus und überschreibt keine Scripts, die bereits defer oder async tragen. Die $skip-Liste lässt sich um weitere Handles erweitern, etwa für ein Script, das zwingend synchron laufen muss.

<?php
// /wp-content/mu-plugins/ihp-defer-scripts.php
add_filter( 'script_loader_tag', function( $tag, $handle, $src ) {
    // Handles, die kein defer bekommen (synchron oder bereits behandelt)
    $skip = [ 'jquery-core', 'jquery-migrate' ];
    if ( in_array( $handle, $skip, true ) ) {
        return $tag;
    }
    // Bereits defer oder async gesetzt? Finger weg.
    if ( str_contains( $tag, ' defer' ) || str_contains( $tag, ' async' ) ) {
        return $tag;
    }
    return str_replace( '<script ', '<script defer ', $tag );
}, 10, 3 );

Frei nutzbar. Wer die Umsetzung, das Testen im Staging oder die Pflege der Skip-Liste abgeben will, weiß, wo wir zu finden sind.

Das Wichtigste zum Mitnehmen

  • Render-blocking entsteht, weil der Browser CSS und synchrone Scripts vollständig verarbeiten muss, bevor er ein Pixel zeichnet. Der Mechanismus ist bewusst so gebaut, das Ausmaß in der Praxis ist das Problem.
  • defer und async sind nicht austauschbar: defer erhält die Ausführungsreihenfolge und passt für alles mit Abhängigkeiten, async passt nur für vollständig isolierte Scripts.
  • Kritisches CSS inline im <head> plus asynchrones Nachladen des vollen Stylesheets ist der größte einzelne Hebel gegen render-blocking CSS.
  • Web-Fonts lokal zu hosten ist schneller als die externe Google-Fonts-Einbindung und vermeidet die datenschutzrechtlich problematische IP-Übertragung an Dritte.

Häufige Fragen

Was ist der Unterschied zwischen defer und async bei Scripts?

defer lädt das Script parallel zum HTML-Parsing, führt es aber erst aus, wenn das gesamte Dokument geparst ist, in der Reihenfolge des Dokuments. async lädt ebenfalls parallel, führt aber sofort nach dem Download aus, ohne Rücksicht auf die Dokumentreihenfolge oder andere Scripts. Beide Attribute wirken nur bei externen Scripts mit src-Attribut, bei Inline-Scripts haben sie keine Wirkung.

Warum zeigt PageSpeed Insights render-blocking Ressourcen, obwohl ich defer verwende?

Weil defer nur externe Scripts betrifft. Inline-Scripts im <head> ohne src-Attribut werden von defer nicht erfasst. Außerdem wertet Lighthouse Stylesheets als render-blocking, wenn sie ohne spezifisches media-Attribut oder ohne asynchrones Nachladen eingebunden sind.

Kann ich alle Scripts auf async umstellen?

Nein. async garantiert keine Ausführungsreihenfolge. Wenn Skript B von Skript A abhängt, aber B schneller heruntergeladen wird als A, wird B zuerst ausgeführt und schlägt fehl. Alles, was jQuery oder andere Libraries voraussetzt, oder was bestimmte DOM-Zustände erwartet, bekommt defer. async passt nur für vollständig isolierte Scripts ohne Abhängigkeiten.

Was ist kritisches CSS, und wie viel sollte es umfassen?

Kritisches CSS sind die Stile, die für den sichtbaren Bereich ohne Scrollen gebraucht werden: Grundraster, Typografie, Farben und Abstände des Bereichs über der Falz. Der Coverage-Tab in Chrome DevTools zeigt, welche Regeln beim ersten Laden aktiv sind. Typischerweise liegt das kritische CSS bei 10 bis 20 KB minimiert. Alles darüber hinaus sollte asynchron nachgeladen werden.

Warum braucht rel=“preload“ für Fonts das crossorigin-Attribut?

Weil Fonts als CORS-Anfragen behandelt werden. Ohne crossorigin erkennt der Browser die vorgelandene Fontdatei beim eigentlichen Font-Request nicht als dieselbe Ressource und fordert sie ein zweites Mal an. Das hebt den Vorteil des Preloads komplett auf. Das Verhalten ist im web.dev-Leitfaden zu preload als häufiger Implementierungsfehler dokumentiert.

Hilft ein CDN gegen render-blocking Ressourcen?

Ein CDN verkürzt die Downloadzeit, weil die Dateien von einem Server nahe beim Nutzer ausgeliefert werden. Es löst aber das strukturelle Problem nicht: Wenn ein Stylesheet den ersten Paint blockiert, blockiert es ihn weiterhin, auch wenn es schneller lädt. Die Lösung ist das asynchrone Laden, nicht nur die schnellere Auslieferung. CDN und kritisches CSS ergänzen sich, das eine ersetzt das andere nicht.

Wie wirken sich render-blocking Ressourcen auf den LCP aus?

Direkt. Der Largest Contentful Paint kann nicht gemessen werden, bevor das Element überhaupt gezeichnet ist. Render-blocking Ressourcen verzögern den Moment, ab dem der Browser das erste Pixel zeichnet, und damit auch den LCP. Wer den LCP unter 2,5 Sekunden bringen will, kommt an render-blocking kaum vorbei. Der LCP-Ratgeber zeigt die weiteren Hebel, die über render-blocking hinausgehen.

Quellen und weiterführende Informationen: MDN Web Docs: script-Attribut defer und async, Lighthouse: Render-blocking Resources (Google Chrome), web.dev: Defer non-critical CSS, web.dev: Preload critical assets, web.dev: Optimize LCP, MDN: How browsers work. Stand: Juni 2026. Angaben ohne Gewähr, technische Details können je nach Browser-Version und Implementierung abweichen.