The Problem with Monolithic CSS
Whether you're relying on a UI framework or writing custom styles, large stylesheets come at a cost. The browser must download and parse all your CSS before it can paint anything, so shipping too much of it directly delays first render.
UI libraries make development faster but often introduce unnecessary bytes. Bootstrap 4, for example, is 187 KB uncompressed; Semantic UI weighs about 730 KB. Even minified and gzipped, Bootstrap is roughly 20 KB — well over the 14 KB threshold for the first network round trip. For pages where the above-the-fold content only needs a fraction of those rules, this is pure overhead.
The Critical npm module solves this by extracting, minifying, and inlining only the CSS required for above-the-fold content. The rest of the stylesheet is loaded asynchronously, so the viewport renders quickly without waiting for the entire CSS payload.
Measuring the Impact
Consider a responsive ice cream gallery built with Bootstrap. Running a Lighthouse performance audit on this site with mobile emulation, simulated Fast 3G, 4x CPU slowdown, and cleared storage produces a telling result: the filmstrip shows a blank screen for a noticeable period before content appears. This delay shows up as a high First Contentful Paint (FCP) time and a poor overall performance score.
The Lighthouse Opportunities section points directly at the culprit: Eliminate render-blocking resources. That's exactly what Critical is designed to handle.
Setting Up Critical
In a Glitch project, Critical is already installed. The work starts in the empty config file, critical.js. The basic structure requires requiring the module and calling critical.generate() with a configuration object:
const critical = require('critical');
critical.generate({
// configuration goes here
}, (err, output) => {
if (err) {
console.error(err);
}
});
Error handling is optional but makes it easy to confirm the operation succeeded from the console.
Helpful Configuration Options
Critical offers a range of options, with full details in the GitHub docs. Key ones include:
base: The base directory used to resolve paths.src: The HTML source file.dest: The output file for the processed HTML.css: An array of CSS file paths to process.widthandheight: The viewport dimensions to target.dimensions: An array of viewport sizes for generating CSS for multiple targets.inline: Whentrue, inlines the critical CSS into the source file's<head>.minify: Minify the extracted CSS.
Defining a Multi-Viewport Configuration
A practical configuration covers multiple screen sizes — one for small phones and another for standard laptops. The dimensions array handles this. When multiple viewport sizes are specified, Critical minifies the extracted CSS automatically, so you can omit the minify option.
A sample configuration looks like this, added to critical.js:
const critical = require('critical');
critical.generate({
base: './',
src: 'index.html',
dest: 'index.html',
inline: true,
dimensions: [
{
height: 500,
width: 300
},
{
height: 720,
width: 1280
}
]
}, (err, output) => {
if (err) {
console.error(err);
}
});
The config uses index.html as both source and destination because inline is enabled. Critical reads the HTML, extracts the critical CSS, and overwrites index.html with the inlined styles in the <head> section.
Running the Extraction
After adding a script to package.json, run the tool from the terminal:
npm run critical
Once complete, the <head> of index.html contains a <style> block with the generated critical CSS, followed by a script that asynchronously loads the remaining stylesheet.
Verifying the Results
Re-running the Lighthouse audit with the same settings as before shows a marked improvement. The filmstrip reveals content appearing much earlier, and the FCP score and overall performance rating reflect the change. By prioritizing just the CSS needed for the first paint, Critical helps ensure the page feels fast on first load.



