Verwijder Render Blocking CSS in Next.js voor Betere Core Web Vitals
Verwijder render blocking CSS in Next.js voor snellere Core Web Vitals

Verwijder render blocking CSS in Next.js
CSS is render blocking. De browser zal geen enkele pixel op het scherm tekenen totdat het elke stylesheet in de <head> heeft gedownload en geparset. In een Next.js app betekent dat standaard twee externe CSS-bestanden: één globale stylesheet en één pagina-specifieke stylesheet. Op een snelle 3G-verbinding kost het downloaden van die twee bestanden je 600ms voordat de browser überhaupt begint met renderen. Dat is 600ms die direct wordt opgeteld bij je First Contentful Paint en Largest Contentful Paint.
Laatst beoordeeld door Arjen Karel in maart 2026
Table of Contents!
- Verwijder render blocking CSS in Next.js
- App Router vs Pages Router
- Optie 1: Genereer Critical CSS (Pages Router)
- Optie 2: Inline alle CSS in de head (Pages Router)
- Optie 3: Styled Components (Pages Router)
- Optie 4: Inline CSS met inlineCss (App Router, Next.js 15+)
- Een opmerking over CSS Modules en Tailwind CSS
- Welke optie moet ik gebruiken?
Gemiddeld meet ik over al mijn klanten en alle apparaten ongeveer 200ms vertraging veroorzaakt door render blocking CSS. Volgens de 2025 Web Almanac faalt 85% van de mobiele pagina's nog steeds voor de audit op render blocking resources. De mediane pagina laadt 8 CSS-bestanden met een totale grootte van 79 KB. Op trage mobiele verbindingen kan render delay goed zijn voor 69% van de totale LCP tijd. Tijd om dit op te lossen.

App Router vs Pages Router
De oplossing hangt af van welke Next.js router je gebruikt. De Pages Router (via _document.tsx) en de App Router (via app/layout.tsx) gaan verschillend om met de levering van CSS. Het inlinen van Critical CSS via critters werkt niet met de App Router omdat streaming incompatibel is met hoe critters HTML verwerkt. Als je de App Router gebruikt, ga dan direct naar Optie 4.
De App Router is de standaard sinds Next.js 13.4. Maar veel productie-apps draaien nog steeds op de Pages Router, en de eerste drie opties hieronder blijven daarvoor geldig.
Optie 1: Genereer Critical CSS (Pages Router)
De snelste optie is om Critical CSS te genereren. Critical CSS is een verzameling CSS-regels die nodig is om het zichtbare deel van de pagina te renderen. Die regels worden inline in de <head> geplaatst. Daarna worden de originele CSS-bestanden parallel gedownload terwijl de browser verder gaat met renderen. Zodra de originele CSS-bestanden zijn gedownload, worden ze in de pagina geïnjecteerd.
Critical CSS is in Next.js beschikbaar als een experimentele feature. Voeg experimental: { optimizeCss: true } toe aan je next.config.js. Next.js bundelt de critters library intern, dus je hoeft deze niet apart te installeren. Let op dat het originele critters pakket is deprecated (vervangen door de beasties fork), maar Next.js is nog niet overgestapt.
const nextConfig = {
reactStrictMode: true,
experimental: { optimizeCss: true }
}
Deze optie werkt alleen met de Pages Router. Het ondersteunt de App Router niet omdat critters de volledig gerenderde HTML nodig heeft, wat incompatibel is met streaming.
Optie 2: Inline alle CSS in de head (Pages Router)
Als je geen experimentele features in je Next.js app wilt inschakelen, kun je overwegen om je CSS handmatig te inlinen. Maak een custom head sectie aan en refereer ernaar in je _document.tsx.
Het nadeel is dat de inline CSS groter zal zijn dan bij de eerste methode, omdat je alles inlinet, niet alleen de kritieke regels. Echter, als je je stylesheets schoon en slank houdt, zal dit de Core Web Vitals voor je Next.js app aanzienlijk verbeteren.
import { Html, Head, Main, NextScript } from "next/document";
import { readFileSync } from "fs";
import { join } from "path";
class InlineStylesHead extends Head {
getCssLinks: Head["getCssLinks"] = ({ allFiles }) => {
const { assetPrefix } = this.context;
if (!allFiles || allFiles.length === 0) return null;
return allFiles
.filter((file: any) => /\.css$/.test(file))
.map((file: any) => (
<style
key={file}
nonce={this.props.nonce}
data-href={`${assetPrefix}/_next/${file}`}
dangerouslySetInnerHTML={{
__html: readFileSync(join(process.cwd(), ".next", file), "utf-8"),
}}
/>
));
};
}
export default function Document() {
return (
<Html>
<InlineStylesHead />
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
Optie 3: Styled Components (Pages Router)
Styled Components is een CSS-in-JS tool waarmee je CSS in JavaScript-bestanden kunt schrijven. Je kunt class names scopen, ongebruikte CSS automatisch verwijderen en stijlen beheren naast je componenten. Voor de Core Web Vitals betekent dit dat alleen de stijlen die op die pagina nodig zijn, worden geïnjecteerd.
Voeg compiler: { styledComponents: true } toe aan je next.config.js, installeer styled-components (yarn add styled-components en yarn add -D @types/styled-components), en update vervolgens _document.js om server side rendering voor styled components te ondersteunen.
const nextConfig = {
reactStrictMode: true,
compiler: {
styledComponents: true,
}
}
import Document, { DocumentContext } from "next/document";
import { ServerStyleSheet } from "styled-components";
export default class MyDocument extends Document {
static async getInitialProps(ctx: DocumentContext) {
const sheet = new ServerStyleSheet();
const originalRenderPage = ctx.renderPage;
try {
ctx.renderPage = () =>
originalRenderPage({
enhanceApp: (App) => (props) =>
sheet.collectStyles(<App {...props} />),
});
const initialProps = await Document.getInitialProps(ctx);
return {
...initialProps,
styles: (
<>
{initialProps.styles}
{sheet.getStyleElement()}
</>
),
};
} finally {
sheet.seal();
}
}
}
Als je de App Router gebruikt met styled-components, heb je een andere setup nodig. Maak een style registry client component aan met useServerInsertedHTML en wrap je root layout hiermee. Styled components werken alleen in Client Components binnen de App Router. Bekijk de Next.js CSS-in-JS gids voor het volledige patroon.
Optie 4: Inline CSS met inlineCss (App Router, Next.js 15+)
Voor de App Router introduceerde Next.js 15 experimental.inlineCss. Dit vervangt alle <link> stylesheet tags door inline <style> tags, waardoor de render blocking waterval volledig wordt geëlimineerd.
const nextConfig = {
experimental: {
inlineCss: true,
}
}
Dit is nog steeds experimenteel en het Next.js team raadt het nog niet aan voor productie. Het inlinet alle CSS (niet alleen Critical CSS), wat de HTML-grootte doet toenemen. Voor sites die Tailwind CSS gebruiken, werkt deze afweging goed omdat Tailwind kleine, atomische CSS-bundels genereert. Voor sites met grote stylesheets kan de HTML-bloat schadelijk zijn voor je Time to First Byte.
Een opmerking over CSS Modules en Tailwind CSS
CSS Modules en Tailwind CSS zijn momenteel de twee populairste stylingbenaderingen in Next.js. Beide compileren naar standaard CSS-bestanden tijdens de build en worden geserveerd als <link> tags. Dat betekent dat ze standaard render blocking zijn.
Tailwind heeft één voordeel: omdat het ongebruikte classes verwijdert, is de output doorgaans erg klein (vaak onder de 10 KB gzipped). De render blocking impact van een bestand van 10 KB is minimaal. CSS Modules kunnen groter worden als je niet oppast met ongebruikte stijlen.
Hoe dan ook, alle bovenstaande opties zijn van toepassing. Als je render blocking CSS volledig wilt elimineren, combineer dan je favoriete stylingbenadering met optimizeCss (Pages Router) of inlineCss (App Router).
Welke optie moet ik gebruiken?
Het hangt af van je router en je CSS-strategie:
- App Router + Tailwind: Gebruik
inlineCss. Kleine CSS-bundels maken inlining praktisch. - App Router + grote CSS: Wacht tot
inlineCssstabiliseert, of gebruik een custom beasties setup. - Pages Router: Gebruik
optimizeCss(Optie 1). Het is de eenvoudigste oplossing en inlinet alleen wat kritiek is. - Pages Router + CSS-in-JS: Gebruik styled-components of Emotion met de SSR patronen zoals hierboven getoond.
Over alle Next.js sites gemonitord door CoreDash, laten degenen die geïnlinete Critical CSS gebruiken een mediane FCP-verbetering van 400ms zien in vergelijking met standaard CSS-levering. Dat is het verschil tussen een goede en een matige FCP-score.
Welke optie je ook kiest, verifieer de resultaten met Real User Monitoring. Lab scores vertellen je wat er zou kunnen gebeuren. Velddata vertelt je wat er daadwerkelijk is gebeurd.
Voor meer informatie over hoe CSS en JavaScript interageren met de rendering pipeline, bekijk de complete gids voor het oplossen van render blocking resources. Als je een Next.js app aan het optimaliseren bent, bekijk dan ook de gidsen over het oplossen van third party scripts en het meten van de Core Web Vitals in Next.js. Voor een bredere blik op laadstrategieën, behandelt de gids voor resource prioritization hoe browsers beslissen wat ze als eerste ophalen.
Performance degrades unless you guard it.
I do not just fix the metrics. I set up the monitoring, the budgets, and the processes so your team keeps them green after I leave.
Start the Engagement
