Kurzantwort
Eine Lighthouse-Warnung zu ungenutztem CSS bedeutet nicht automatisch, dass die gemeldeten Regeln im gesamten Projekt überflüssig sind. Das Tool betrachtet eine konkrete Seite und einen konkreten Lauf. Styles für ein Menü, Modal, einen anderen Breakpoint oder eine andere Route können dabei ungenutzt erscheinen und trotzdem erforderlich sein.
Die sichere Reihenfolge lautet:
- Produktions-Bundle und tatsächliche Byte-Ersparnis messen.
- Verursachendes Stylesheet und Import-Grenze finden.
- Globale Styles, Third-Party-CSS und überbreite Tailwind-Quellen zuerst prüfen.
- Kleine Änderung durchführen.
- Alle relevanten Routen, Breakpoints und Interaktionszustände visuell testen.
Das Ziel ist nicht „0 % ungenutztes CSS“, sondern weniger render-blockierende Bytes ohne Regressionen.
Was Lighthouse tatsächlich meldet
Externe Stylesheets müssen heruntergeladen und verarbeitet werden, bevor der Browser die Darstellung abschließen kann. Die Chrome-Dokumentation zum Lighthouse-Audit erklärt deshalb, dass ungenutzte Regeln zusätzliche Netzwerk- und Style-Berechnungsarbeit verursachen können.
Die Messung hat jedoch Grenzen:
- Sie gilt für die geprüfte URL, nicht für alle Routen.
- Sie sieht nur Zustände, die während des Laufs aktiviert wurden.
- Hover, Focus, geöffnetes Mobile-Menü, Dialoge und nachgeladene Komponenten können fehlen.
- Ein warmer Entwicklungsserver ist kein verlässlicher Ersatz für einen Production Build.
- Die theoretische Ersparnis ist nicht automatisch der wichtigste Performance-Engpass.
Prüfen Sie daher neben dem Prozentwert auch die absolute Größe. 70 % ungenutzt in einer 8-KiB-Datei ist häufig weniger relevant als 25 % in einem 300-KiB-Framework-Stylesheet.
Wo ungenutztes CSS in Next.js entsteht
Zu viel im globalen Stylesheet
Styles aus einem Root Layout gelten bewusst für viele Routen. Dort gehören Reset, Tokens, Grundtypografie und wirklich globale Elemente hin. Komponentenspezifische Karten-, Tabellen- oder Marketing-Styles erhöhen dagegen den CSS-Anteil auf Seiten, die diese Komponenten nie rendern.
Next.js unterstützt lokal begrenzte CSS Modules. Die Next.js-Dokumentation beschreibt, dass CSS-Module im Production Build in minifizierte und aufgeteilt geladene CSS-Dateien überführt werden. Das ist ein guter Grund, lokale Komponentenregeln nicht vorsorglich global zu importieren.
Layouts mit zu großer Reichweite
Ein Stylesheet in einem gemeinsamen Layout wird für alle darunterliegenden Routen relevant. Importieren Sie Admin-, Dashboard- oder Editor-CSS deshalb möglichst im engsten gemeinsamen Layout oder in der Komponente, die es tatsächlich benötigt.
Komponentenbibliotheken und alte Themes
Datepicker, Editoren, Charts und UI-Kits bringen häufig komplette Stylesheets mit. Besonders verdächtig sind:
- ein global importiertes Theme für eine Komponente auf nur einer Route;
- zwei parallele Design-Systeme während einer Migration;
- Styles einer entfernten Bibliothek, deren Import zurückblieb;
- Kopien eines Vendor-Stylesheets in mehreren Entry Points.
CSS-in-JS ohne passende Server-Integration
Bei CSS-in-JS im App Router muss die jeweilige Library die aktuellen React- und Server-Rendering-Mechanismen unterstützen. Die aktuelle Next.js-Anleitung weist darauf hin, dass dafür eine Style Registry und useServerInsertedHTML nötig sein können. Eine falsche Integration kann doppelte, verspätete oder unnötig globale Styles erzeugen.
Tailwind: zwei verschiedene Fehler nicht verwechseln
Tailwind scannt Quelldateien als Text und erzeugt CSS für erkannte vollständige Utility-Namen. Die offizielle Tailwind-Dokumentation nennt zwei wichtige Konsequenzen:
- Dynamisch zusammengesetzte Namen können fehlen.
bg-${color}-600ist für den Scanner nicht zuverlässig erkennbar. Verwenden Sie stattdessen ein Mapping mit vollständigen Klassennamen. - Explizit erzwungene Quellen können zu viel erzeugen.
@source inline()ist nützlich für wirklich dynamisch benötigte Utilities. Breite Ranges oder vorsorgliche Varianten erzeugen aber CSS, das viele Seiten nie verwenden.
Fehlende dynamische Klassen verursachen kaputte Darstellung; zu breite @source-Regeln verursachen Ballast. Beides braucht unterschiedliche Korrekturen.
Weitere typische Tailwind-Ursachen:
- ein Monorepo scannt Verzeichnisse, die für dieses Frontend nicht relevant sind;
- eine externe Komponentenbibliothek wurde vollständig als Quelle registriert;
- alte Safelist-/Source-Regeln blieben nach einem Refactoring erhalten;
- ein generiertes Content-Verzeichnis enthält viele Utility-Tokens, die nie gemeinsam auf einer Route erscheinen.
Diagnose: vom Report zur Ursache
1. Production Build verwenden
Erstellen Sie einen Production Build und testen Sie die tatsächlich ausgelieferte Seite. Development Mode enthält zusätzliche Mechanismen und ist für Bundle-Bewertungen ungeeignet.
2. CSS-Datei identifizieren
Notieren Sie aus Lighthouse oder dem Network Panel:
- URL und übertragene Größe;
- Initiator bzw. importierendes Layout/Modul;
- Cache-Status;
- geschätzte ungenutzte Bytes.
3. Coverage mit echten Zuständen aufnehmen
Starten Sie im Chrome DevTools Coverage Panel eine Aufzeichnung und führen Sie die relevanten Zustände aus:
- Desktop und Mobile Breakpoint;
- Navigation und Route Change;
- Menü, Modal, Tabs, Accordions und Dropdowns;
- Formfehler, Focus und Disabled State;
- nachgeladene Widgets oder personalisierte Bereiche.
Coverage ist ein Diagnosewerkzeug, keine automatische Löschliste.
4. Import-Grenze korrigieren
Die wirksamste Änderung ist oft nicht das Löschen einzelner Selektoren, sondern eine kleinere Reichweite:
- Component CSS in ein CSS Module verschieben;
- Vendor-CSS nur zusammen mit der betreffenden Komponente laden;
- ein großes Root-Stylesheet auf Root und Sub-Layout aufteilen;
- ungenutztes Theme oder entfernte Bibliothek vollständig löschen;
- Tailwind-Quellen und explizite Safelists enger definieren.
5. Wirkung erneut messen
Dokumentieren Sie vor und nach der Änderung:
| Messwert | Vorher | Nachher |
|---|---|---|
| CSS übertragen, kalter Cache | ||
| Render-blockierende CSS-Zeit | ||
| LCP/Paint im gleichen Testprofil | ||
| Visuelle Regressionen |
Nur gleiche URL, Gerätedrosselung und Cache-Bedingungen ergeben einen brauchbaren Vergleich.
Sicherer Cleanup-Plan
- Offensichtlichen Altbestand entfernen: nicht mehr importierte Themes, tote Vendor-Dateien, doppelte Font-/Reset-Regeln.
- Globale Reichweite reduzieren: nur Design-Tokens, Reset und echte Site-Grundlagen global halten.
- Komponenten lokalisieren: CSS Modules oder engere Layout-Imports verwenden.
- Tailwind-Quellen prüfen: vollständige Klassennamen mappen und erzwungene Utilities minimieren.
- In kleinen Änderungen liefern: pro Pull Request eine Ursache statt eines pauschalen Stylesheet-Rewrites.
- Visuell absichern: Screenshot-Tests oder mindestens eine dokumentierte Route-State-Matrix nutzen.
Was Sie nicht tun sollten
- Selektoren allein aufgrund eines einzelnen Lighthouse-Laufs löschen.
hover:,focus:,aria-*,data-*oder responsive Varianten ohne State-Test entfernen.- CSS vor größeren Engpässen wie Bildern, Fonts oder unnötigem Client-JavaScript optimieren.
- Critical CSS manuell duplizieren, ohne zu prüfen, ob dieselben Regeln anschließend nochmals geladen werden.
- Tailwind-Klassen aus Props per String-Interpolation bauen und das Problem mit einer riesigen Safelist überdecken.
Fazit
Ungenutztes CSS ist ein Performance-Signal, kein Qualitätsurteil. In Tailwind- und Next.js-Projekten entstehen die größten sicheren Verbesserungen meist durch engere Import-Grenzen, kleinere globale Stylesheets, gezielt registrierte Tailwind-Quellen und das Entfernen ganzer veralteter Abhängigkeiten.
Wer absolute Bytes misst, interaktive Zustände testet und Änderungen schrittweise ausliefert, reduziert CSS ohne die schwer auffindbaren Layoutfehler eines aggressiven „Purge“-Ansatzes.
Weiterführend: Technical SEO und Relaunch Engineering.