krisawzm/critical-css
Laravel package that speeds up page rendering by extracting and inlining critical CSS, so above-the-fold content paints immediately while the full stylesheet loads asynchronously.
Install it as a build-time dependency. The package is a generator, not a request-time service, so prefer:
composer require krisawzm/critical-css --dev
If you need to generate on production hosts without Composer dev dependencies, install it normally but keep generation out of the request lifecycle.
Publish and inspect the config first. Run:
php artisan vendor:publish
Pick the krisawzm/critical-css provider from the list, then read the published config file. That file is the contract for URLs, output paths, viewport dimensions, and any binary/Node path. Confirm the service provider is registered in config/app.php if the package predates Laravel package discovery.
Verify the runtime dependency. This package is from the Laravel 5 era and typically shells out to a Node-based critical CSS tool. Check the README and command source for whether it expects critical, phantomjs, or another binary on PATH. Run the binary manually before debugging the Laravel side:
which critical
critical --version
Start with one public page. Pick a simple, unauthenticated page such as /. Generate critical CSS for a single viewport, write it to a known path, and inspect the output before wiring it into Blade. This isolates package/config problems from layout problems.
Where to look first, in order:
README.md for the exact command name and config keys.php artisan list to confirm the actual command signature.First useful integration. Generate CSS for the home page after your frontend assets are built, then inline it in your main layout with a fallback to the normal stylesheet. That single-page setup is enough to prove the pipeline before scaling to every route.
Generate during deployment, never during a normal request. The typical production pattern is:
npm run production
php artisan cache:clear
php artisan criticalcss:generate # check the real command name
Run this after assets exist and after the application is reachable at the URL the generator will crawl. On Forge, Envoyer, or a CI runner, put it in the deploy script and fail the deploy if generation fails for critical pages.
Use a view composer or middleware to inject the CSS. Keep the layout clean:
View::composer('layouts.app', function ($view) {
$key = md5(request()->path());
$path = storage_path("app/critical/{$key}.css");
$view->with(
'criticalCss',
file_exists($path) ? file_get_contents($path) : null
);
});
Then in the layout:
@if (! empty($criticalCss))
<style>{!! $criticalCss !!}</style>
<link rel="preload" href="{{ mix('css/app.css') }}" as="style"
onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="{{ mix('css/app.css') }}"></noscript>
@else
<link rel="stylesheet" href="{{ mix('css/app.css') }}">
@endif
Key generated files by route and asset version. A common mistake is generating once and never invalidating. Include the mix-manifest.json hash or the output CSS file's modification time in the cache key:
$assetHash = md5_file(public_path('css/app.css'));
$cacheKey = md5(request()->path() . '|' . $assetHash);
Maintain a route-to-output map. For multi-page sites, keep an explicit config or array of important URLs, viewports, and output filenames. Do not crawl the entire site on every deploy. Prioritize the landing page, high-traffic templates, and anything with a distinct layout.
Keep a fallback path for every page. If the generated file is missing, stale, empty, or too large, render the normal stylesheet link. Critical CSS should be an optimization, not a hard dependency for rendering.
Disable or stub generation locally. Requests and deploys should not block on a headless browser. Use a local flag, a cached file, or a container binding that returns empty CSS in the local environment while still letting you run the artisan command manually.
Pair it with a proper full-CSS loading strategy. Inline critical CSS, then load the full CSS asynchronously with preload/onload and a <noscript> fallback. Also preload the main font files if typography is part of the above-the-fold experience.
Version the artifacts if you cannot run generation on the server. You can generate locally or in CI, commit the CSS files to a dedicated directory, and deploy them as static assets. This is often more reliable with an old Node toolchain than trying to reproduce the environment on every web node.
critical release. Modern Node versions may not run them. Pin Node in CI or Docker, or treat this package as a thin wrapper you may need to replace while keeping the same Blade integration.APP_URL, asset(), CDN domains, and http versus https mismatches can produce pages with missing CSS. Inspect the generated HTML or the tool's debug output when critical CSS comes back nearly empty.font-display, preload key fonts, and set explicit dimensions or placeholders for hero images to avoid layout shift.How can I help you explore Laravel packages today?