Wie entfernt man Render-Blocking CSS und JS? (Async, Defer, Critical CSS)

Wie entfernt man Render-Blocking CSS und JS? (Async, Defer, Critical CSS)

Zuletzt überprüft: 22. September 2026
8 Min. Lesezeit
Leitfaden
Core Web Vitals

Wenn der Browser deine Seite lädt, liest er den HTML-Code Zeile für Zeile. Trifft er auf <script src="große-datei.js"> oder <link rel="stylesheet">, stoppt er alles andere, lädt die Datei herunter und führt sie aus.

Erst dann rendert er den Rest der Seite. Das ist “Render-Blocking”.

Im Jahr 2026, wo Core Web Vitals zählen (besonders LCP - Largest Contentful Paint), musst du das beheben.

#1. JavaScript: Async und Defer

Alte Schule sagte: “Skripte in den Footer (wp_footer)”. Neue Schule sagt: “Nutze Attribute”.

  • <script async>: Lädt im Hintergrund, führt sofort nach Download aus (riskant bei Abhängigkeiten, z.B. jQuery).
  • <script defer>: Lädt im Hintergrund, führt erst nach HTML-Laden aus (sicher, bewahrt Reihenfolge).

Wie fügt man defer in WordPress hinzu? Caching-Plugins (WP Rocket, Autoptimize, LiteSpeed Cache) haben eine “Defer JS” Option. Aktiviere sie.

Das löst normalerweise 90% der JS-Probleme.

#2. CSS: Critical CSS

CSS ist schwieriger. Du kannst es nicht “verzögern”, weil die Seite kurzzeitig wie “roher Text” aussieht (ungestylt - FOUC-Effekt).

Die Lösung ist Critical CSS.

  1. Nimm nur das CSS, das für “Above the Fold” Inhalt (sichtbar ohne Scrollen) nötig ist.
  2. Füge es inline in <style> im Header ein.
  3. Lade den Rest des CSS (Footer, untere Abschnitte) asynchron im Hintergrund.

Die meisten modernen Optimierungs-Plugins generieren Critical CSS automatisch.

#Strategie-Zusammenfassung

  1. JS: Alles mit defer (außer absolut kritische Analytics/Cookie-Skripte).
  2. CSS: Critical CSS inline + Rest asynchron.
  3. Fonts: Nutze font-display: swap.

So sieht der Nutzer Inhalte sofort, während schwere Galerie- oder Karten-Skripte im Hintergrund laden.

#Zuerst messen, welche Datei wirklich im Weg steht

Lighthouse nennt dir die blockierenden Dateien, sagt aber nichts darüber, wie viel davon überhaupt gebraucht wird. Öffne die DevTools, starte “Show Coverage” über die Befehlspalette und lade die Seite neu. Die Spalte “Unused Bytes” trennt zwei völlig verschiedene Probleme voneinander: zu viel CSS, oder CSS zum falschen Zeitpunkt. Bei einem Theme mit Pagebuilder liegt der ungenutzte Anteil auf der Startseite häufig bei 70 bis 90 Prozent, und dann ist Minifizieren die falsche Antwort.

Im Netzwerk-Tab suchst du danach nach kleinen Dateien, die spät mit dem Download beginnen. Das sind fast immer Ressourcen, die der Browser erst entdeckt hat, nachdem er eine andere Datei geparst hatte. Genau die gehören in ein preload, alles andere nicht.

#Welches Attribut wofür

AttributDownloadAusführungReihenfolge bleibtGeeignet für
keinesblockiert das Parsensofortjamöglichst nie im <head>
asyncparallelsobald die Datei da istneineigenständige Skripte ohne Abhängigkeiten
deferparallelnach dem Parsen des HTMLjaalles, was jQuery oder andere Skripte braucht
type="module"parallelnach dem ParsenjaES-Module, defer ist eingebaut

Praktische Regel: defer ist der Normalfall, async die Ausnahme. Denn async führt in der Reihenfolge aus, in der die Downloads zufällig fertig werden. Ein Galerie-Plugin, das jQuery(...) aufruft, bevor jQuery geladen ist, wirft einen TypeError in die Konsole und zeigt eine leere Galerie. Auf dem Entwicklungsrechner tritt das selten auf, weil dort alles im Cache liegt und ohnehin in der passenden Reihenfolge ankommt.

#Defer in WordPress ohne Plugin

Seit WordPress 6.3 gibt es das Argument strategy in wp_enqueue_script(). Das ist heute der richtige Weg, weil WordPress die Abhängigkeitskette selbst prüft:

wp_enqueue_script(
    'theme-galerie',
    get_template_directory_uri() . '/js/galerie.js',
    array( 'jquery' ),
    '1.2.0',
    array(
        'in_footer' => true,
        'strategy'  => 'defer',
    )
);

Die angegebene Abhängigkeit ist der eigentliche Gewinn: WordPress verweigert das Verzögern, solange jQuery selbst nicht verzögert wird. Der klassische Fehler ist damit technisch ausgeschlossen.

Für ältere Installationen oder für Plugins, die du nicht anfassen kannst, bleibt der Filter:

add_filter( 'script_loader_tag', 'de_defer_ausgewaehlte_skripte', 10, 2 );

function de_defer_ausgewaehlte_skripte( string $tag, string $handle ): string {
    $verzoegert = array( 'slider', 'lightbox', 'karte' );

    return in_array( $handle, $verzoegert, true )
        ? str_replace( ' src', ' defer src', $tag )
        : $tag;
}

Wichtig ist die Richtung der Liste. Eine Positivliste nennt die Handles, die verzögert werden dürfen. Eine Negativliste (“alles außer diesen”) verzögert auch jedes Skript, das das nächste installierte Plugin hinzufügt, und der Fehler entsteht dann ohne eine einzige Codeänderung.

#Skripte, die gar nicht erst geladen werden sollten

Der schnellste Request ist der, der nicht stattfindet. WooCommerce lädt seine Cart-Fragments und Stylesheets auf jeder Seite, auch auf einer reinen Textseite ohne Shop-Bezug:

add_action( 'wp_enqueue_scripts', 'de_shop_assets_nur_im_shop', 99 );

function de_shop_assets_nur_im_shop(): void {
    if ( function_exists( 'is_woocommerce' ) && ! is_woocommerce() && ! is_cart() && ! is_checkout() ) {
        wp_dequeue_script( 'wc-cart-fragments' );
    }
}

Vor dem Deployment gehört dazu ein Test mit gefülltem Warenkorb. Wer wc-cart-fragments global entfernt, bekommt einen Warenkorb-Zähler im Header, der nach dem Hinzufügen eines Artikels stehenbleibt, und das fällt im Zweifel erst im Support auf.

#Critical CSS, ohne dass die Seite flackert

Das Muster ist immer dasselbe: das kritische CSS inline im <head>, den Rest nicht blockierend nachladen.

<style>/* nur Regeln für den sichtbaren Bereich */</style>
<link rel="preload" href="/style.css" as="style"
      onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="/style.css"></noscript>

Die noscript-Zeile ist keine Verzierung. Ohne sie bekommen Besucher mit deaktiviertem JavaScript überhaupt kein Stylesheet, und das betrifft auch Firmennetze mit strenger Inhaltsfilterung.

Drei Dinge entscheiden über das Ergebnis. Erstens die Größe: bleibt der Inline-Block unter etwa 15 KB, lohnt sich der Tausch, darüber bezahlst du jeden einzelnen Seitenaufruf mit einer längeren HTML-Antwort. Zweitens der Viewport: Critical CSS, das bei 1300 Pixeln Breite erzeugt wurde, kennt die reinen Mobilregeln nicht, also für beide Breiten erzeugen und zusammenführen. Drittens der Test unter schlechter Verbindung: in den DevTools auf “Slow 3G” stellen und neu laden. Wenn für einen Moment unformatierter Text zu sehen ist, bevor das Layout einrastet, fehlt im kritischen Block etwas.

#Schriften, der vergessene Blocker

Eine Webfont ohne font-display erzeugt FOIT: der Browser versteckt den Text, bis die Schriftdatei da ist. Auf einer schwachen Mobilverbindung sind das mehrere Sekunden leere Fläche.

@font-face {
    font-family: 'Inter';
    src: url('/fonts/inter.woff2') format('woff2');
    font-display: swap;
}

Mit swap erscheint der Text sofort in der Systemschrift und wechselt, sobald die Datei geladen ist. Ergänze ein Preload, und zwar mit crossorigin, das bei Schriften auch dann verlangt wird, wenn die Datei von der eigenen Domain kommt:

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

In Deutschland kommt zum Tempoargument ein rechtliches: die dynamische Einbindung von Google Fonts überträgt die IP-Adresse der Besucher an einen Drittanbieter. Das war 2022 Gegenstand eines viel zitierten Urteils des Landgerichts München I und hat eine Welle von Abmahnschreiben ausgelöst. Selbst hosten löst beide Fragen auf einmal, denn es spart zusätzlich DNS-Auflösung und TLS-Handshake zu einer fremden Domain.

Auf deutschsprachigen Seiten ist der Consent-Manager oft das größte blockierende Skript überhaupt, und er muss vor allem anderen laufen, weil er entscheidet, was danach überhaupt geladen werden darf. Daraus folgt eine unangenehme Konsequenz: Tracking hinter dem Banner zu verzögern bringt für die gemessenen Werte fast nichts, wenn das Banner selbst synchron im <head> hängt. Prüfe deshalb zuerst, ob dein Anbieter eine schlanke Inline-Variante für die reine Anzeige anbietet und die schwere Logik nachlädt.

Chat-Widgets lädst du erst bei echter Interaktion:

addEventListener('scroll', function laden() {
    const s = document.createElement('script');
    s.src = 'https://widget.example.com/chat.js';
    s.defer = true;
    document.body.appendChild(s);
}, { once: true });

Für Videos und Karten nimmst du eine Fassade: ein Standbild, das aussieht wie der Player, und den echten iframe erst beim Klick. Das Paket lite-youtube-embed macht genau das und reduziert eine YouTube-Einbindung von mehreren hundert Kilobyte auf wenige.

#Vorher und nachher messen

Lighthouse liefert Labordaten und damit schnelles Feedback pro Änderung. Was in der Search Console erscheint, sind dagegen Felddaten aus dem Chrome User Experience Report. Beide widersprechen sich nicht, sie messen Verschiedenes: eine Messung auf einem Gerät gegen ein rollierendes Fenster von 28 Tagen über echte Geräte und echte Verbindungen.

Daraus folgt praktisch: Wenn die Search Console am Tag nach dem Deployment unverändert aussieht, ist das kein Befund. Das Fenster muss erst durchlaufen. Notiere das Datum der Veröffentlichung, sonst lässt sich später nicht mehr sagen, welcher Teil der Kurve zu welcher Änderung gehört.

#Fünf Fehler, die am meisten kosten

  • async auf etwas, das jQuery braucht. Leere Galerien und Formulare, die nicht senden, und das nur bei langsamer Verbindung.
  • Zu viel Inline-CSS. Über etwa 15 KB zahlt jeder Seitenaufruf mit.
  • Mobilen Viewport beim Critical CSS vergessen. Auf dem Handy wird gemessen, was am Ende zählt.
  • Negativliste statt Positivliste beim Verzögern von Skripten. Das nächste Plugin wird dann dein Problem.
  • Nach Plugin-Updates nicht erneut prüfen. Plugins ändern, was sie einreihen, und ein Setup, das im letzten Jahr funktioniert hat, kann heute still gebrochen sein.

Mehr über unsere WordPress-Geschwindigkeitsoptimierung.

Nächster Schritt

Machen Sie aus dem Artikel eine echte Umsetzung

Dieser Block stärkt die interne Verlinkung und führt Nutzer gezielt zum nächsten sinnvollen Schritt im Service- und Content-System.

Soll das Thema auf Ihrer Website umgesetzt werden?

Wenn Core Web Vitals, Rendering oder WordPress-Overhead das Problem sind, setze ich einen klaren Optimierungsplan auf und implementiere ihn.

Artikel-FAQ

Häufig gestellte Fragen

Praktische Antworten zur Umsetzung des Themas.

SEO-readyGEO-readyAEO-ready3 Q&A
Was ist der Unterschied zwischen async und defer?#
async lädt das Skript parallel und führt es aus, sobald es bereit ist, was Abhängigkeiten zerstören kann. defer lädt ebenfalls parallel, führt das Skript aber erst aus, nachdem das HTML vollständig verarbeitet wurde.
Was ist Critical CSS?#
Das ist der minimale Satz an Stilen, der nötig ist, um den Inhalt oberhalb der Falz darzustellen. Das übrige CSS kann später und asynchron geladen werden.
Kann ich Lazy Loading auf alles anwenden?#
Nein. Bilder und kritische Ressourcen im oberen Seitenbereich dürfen nicht verzögert werden. Ziel ist eine schnellere erste Darstellung, nicht ein verzögerter Hauptinhalt.

Sie brauchen ein FAQ für Branche und Zielmarkt? Wir erstellen eine Version passend zu Ihren Business-Zielen.

Kontakt aufnehmen

Ähnliche Artikel