Kritische CSS splitsen in Tailwind v3/v4 op Laravel + Vite

Als een pagina traag aanvoelt, staren gebruikers naar een leeg scherm terwijl CSS het renderen blokkeert. Een pragmatische oplossing is om precies genoeg stijlen te leveren voor de above-the-fold weergave en de rest uit te stellen. Deze handleiding laat een schone setup met twee ingangen zien in Laravel + Vite, met productieklare voorbeelden voor Tailwind v3 en v4, waarom PageSpeed/Core Web Vitals belangrijk is en wat je moet vermijden.

Kritische CSS splitsen in Tailwind v3/v4 op Laravel + Vite

Waarom PageSpeed belangrijk is (LCP/CLS)

Kritische CSS is de minimale set stijlen die nodig is om het eerste scherm (above-the-fold) te renderen. Door dit deel vroeg aan te leveren (inline of als een klein bestand) en de resterende CSS uit te stellen, verminder je renderblokkerend werk en verbeter je LCP. Het zorgvuldig instellen van lettertypen kan ook onverwachte verschuivingen in de lay-out verminderen en CLS helpen.

Basisstrategie (Laravel + Vite)

  1. Twee ingangspunten:critical.css voor het eerste scherm; app.css voor al het andere (plugins, uitgebreide hulpprogramma's, typografie in lange vorm).
  2. Laadvolgorde: lever het belangrijkste op in <head> (inline of een normale link). Stel de rest uit met rel="preload" as="style" + onload en een <noscript> fallback.
  3. Vermijd duplicaten: houd basis/componenten in kritisch en verplaats het grootste deel van de hulpprogramma's naar de uitgestelde bundel; zorg ervoor dat de bronbestanden die door elke build worden gescand elkaar niet overlappen.

Tailwind v3: twee configuraties + een preset

1) Deel je thema één keer

// tailwind.shared.js
module.exports = {
  theme: {
    extend: {
      // colors, spacing, etc.
    },
  },
  plugins: [],
};

2) Kritische build (scan alleen sjablonen boven de vouw)

// tailwind.critical.config.js
module.exports = {
  presets: [require('./tailwind.shared')],
  content: [
    './resources/views/layouts/app.blade.php',
    './resources/views/partials/header.blade.php',
    './resources/views/home/hero.blade.php',
  ],
};
/* resources/css/critical.css */
@config "tailwind.critical.config.js";
@tailwind base;
@tailwind components;
@tailwind utilities;

3) App bundel (sluit bestanden uit die door kritisch worden gebruikt)

// tailwind.app.config.js
module.exports = {
  presets: [require('./tailwind.shared')],
  content: [
    './resources/**/*.blade.php',
    './resources/**/*.vue',
    '!./resources/views/partials/header.blade.php',
    '!./resources/views/home/hero.blade.php',
  ],
};
/* resources/css/app.css */
/* Avoid duplicating base/components (already shipped in critical) */
@config "tailwind.app.config.js";
@tailwind utilities;

Als je dynamische klassenamen hebt, voeg ze dan toe aan safelist in beide configuraties.

4) Bouwen en verbinden via Vite (Laravel)

// vite.config.ts
import { defineConfig } from 'vite'
import laravel from 'laravel-vite-plugin'

export default defineConfig({
  plugins: [
    laravel({
      input: [
        'resources/css/critical.css',
        'resources/css/app.css',
        'resources/js/app.js',
      ],
      refresh: true,
    }),
  ],
})
<!-- Blade: load critical normally (or inline it) -->
@vite('resources/css/critical.css')

<!-- Defer the rest: preload + onload + noscript -->
@php $appCss = Vite::asset('resources/css/app.css'); @endphp
<link rel="preload" as="style" href="{{ $appCss }}" onload="this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="{{ $appCss }}"></noscript>

Tailwind v4: CSS-first sources met fijnmazige controle

In Tailwind v4 is de configuratie CSS-first. Om overlappingen tussen kritieke en app-bundels te voorkomen, schakel je automatisch scannen uit en declareer je sources expliciet.

1) Gedeelde tokens

/* resources/css/theme.css */
@theme {
  /* brand tokens, breakpoints, etc. */
  --color-brand-500: oklch(0.72 0.12 250);
  --breakpoint-2xl: 96rem;
}

2) Kritische CSS: scan alleen wat nodig is

/* resources/css/critical.css */
@import "tailwindcss" source(none);
@import "./theme.css";

/* Enumerate just the above-the-fold templates */
@source "../views/layouts/app.blade.php";
@source "../views/partials/header.blade.php";
@source "../views/home/hero.blade.php";

/* Import required layers explicitly */
@layer theme, base, components, utilities;
@import "tailwindcss/theme" layer(theme);
@import "tailwindcss/base" layer(base);
@import "tailwindcss/components" layer(components);
@import "tailwindcss/utilities" layer(utilities);

3) App CSS: al het andere (sluit uit wat kritisch al omvat)

/* resources/css/app.css */
@import "tailwindcss" source(none);
@import "./theme.css";

/* Scan the project... */
@source "../views/**/*.blade.php";
/* ...except templates you already used for critical */
@source not "../views/partials/header.blade.php";
@source not "../views/home/hero.blade.php";

/* App bundle: keep it lean for post-fold content */
@layer theme, utilities;
@import "tailwindcss/theme" layer(theme);
@import "tailwindcss/utilities" layer(utilities);

/* Inline safelist if you generate classes dynamically */
@source inline("md:grid lg:gap-6 bg-brand-500");

4) Vite setup en Blade laden

// vite.config.ts (same as v3)
import { defineConfig } from 'vite'
import laravel from 'laravel-vite-plugin'

export default defineConfig({
  plugins: [
    laravel({
      input: [
        'resources/css/critical.css',
        'resources/css/app.css',
        'resources/js/app.js',
      ],
      refresh: true,
    }),
  ],
})
<!-- Blade: same pattern as v3 -->
@vite('resources/css/critical.css')
@php $appCss = Vite::asset('resources/css/app.css'); @endphp
<link rel="preload" as="style" href="{{ $appCss }}" onload="this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="{{ $appCss }}"></noscript>

Wat hoort in kritisch (en wat niet)

  • Opnemen: basisinstellingen, header/nav-structuur, heldensectie, essentiële knoppen/links, minimale typografie op het eerste scherm.
  • Vermijd: zware onderdelen onder de vouw, langwerpige .prose typografie, zeldzame widgets.

Lettertypen & CLS-minirecepten

Lay-out verschuivingen treden vaak op wanneer het fallback lettertype wordt vervangen door het weblettertype. Gebruik size-adjust en gerelateerde metric overrides om beter overeen te komen met het fallback lettertype en laad alleen de echt kritieke vlakken vooraf.

@font-face {
  font-family: "InterVar";
  src: url("/fonts/InterVar.woff2") format("woff2");
  font-weight: 100 900;
  font-display: swap;
  /* Tweak metrics to reduce shifts */
  size-adjust: 100%;
  ascent-override: 92%;
  descent-override: 24%;
  line-gap-override: 0%;
}

Controleer het resultaat

  • Voer PageSpeed/Lighthouse uit en vergelijk LCP; controleer "Verminder render-blocking bronnen" en "Verminder ongebruikte CSS".
  • Sanity check: controleer of er geen duplicatie is tussen bundels; als je extra gewicht ziet, bekijk dan de gescande bronnen opnieuw.
  • Onthoud: labscores zijn indicatief; let op de algemene trend en veldgegevens.

Veelvoorkomende valkuilen

  • Overlappende bronnen → duplicaten: in v3, repareer je content globs; in v4, gebruik source(none) met expliciete @source en @source not.
  • Plugins/typografie in kritisch: dit maakt het bestand gemakkelijk voller - houd het in app.css.
  • Inlining kritisch vs CSP: als je CSP streng is, verzend kritisch dan als een klein extern bestand.
  • migratie v3 → v4: verplaats tokens van theme.extend naar @theme, schakel van content naar @source en geef de voorkeur aan CSS-first imports.

Alternatieven als twee-entry niet jouw ding is

  • Automatisch gegenereerde kritieke (bijv. kritieke, beestjes): het snelst om te beginnen; moeilijker om te debuggen op complexe sjablonen.
  • Enkele configuratie + meerdere bronnen: houd één config (v3) of CSS-first setup (v4) en beheer inclusie/exclusie via globs/@source.
  • Route-level CSS: bundels per pagina alleen geladen waar nodig; krachtig maar voegt infra complexiteit toe.
  • Component-scoped kritisch: inline kleine stijlen voor belangrijke boven-de-vouw componenten; discipline vereist, werkt goed voor herhaalde blokken.

Samenvatting

Met een kleine kritische bundel in <head> en een uitgestelde hoofdbundel geef je de browser minder om op te blokkeren en gebruikers een snellere eerste paint. Tailwind v3 geeft de voorkeur aan twee configs en zorgvuldige content paden; Tailwind v4 maakt dit nog netter met CSS-first @source controle. Op Laravel + Vite is het een eenvoudige, onderhoudbare opzet die de waargenomen snelheid meetbaar verbetert.


Neem contact op

Een project in gedachten?

eel je context en gewenst resultaat. Binnen 1 werkdag sturen we de eenvoudigste volgende stap (tijdlijn, ruwe begroting of snelle audit).

Door te verzenden ga je ermee akkoord dat we je gegevens verwerken om op je aanvraag te reageren en, indien van toepassing, precontractuele stappen te nemen op jouw verzoek (AVG art. 6(1)(b)) of op basis van ons gerechtvaardigd belang (art. 6(1)(f)). Deel geen bijzondere persoonsgegevens. Zie ons Privacybeleid.
Reactie binnen 1 werkdag.