With tools such as PostCSS, and servers serving zipped styles across CDN, maintaining a single request to the styles; does it really benefit from breaking up the styles these days?
Also, I’m going to assume, besides the core styles that run a website, anything that is loaded later can come in with its specific styles as part of the HTML/JS.
For the critical CSS thing, we used to kinda do it by hand with some automation more as a toolset to help us decide how much to include (inside the HTML itself - `<styles>`) and then insert the stylesheet. But then, we always found it better to set a Stylesheet Budget and work with it.
I also see that this brings in CSS variable definitions (sorry, ~custom properties~) and things like that. Since critical CSS's size matters so much, it might be worth giving an option to compile all of that down.
> Place your original non-critical CSS <link> tags just before the closing </body> tag
I don't recommend doing this: you still want the CSS downloaded urgently, critical CSS is a façade. Moving to the end of body means the good stuff is discovered late, and thus downloaded late (and will block render if the preloader[0] discovers it).
These days I'd recommend:
<link rel="preload" href="styles.css" as="style" onload="this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="styles.css"></noscript>
[0] https://web.dev/articles/preload-scannerEdit regarding replies to this comment: I'm sure many will get a kick out of your workarounds and they're all worth posting in the spirit of HN, however I am talking about CSPs that disallow shenanigans. Carry on though :^)
Even when they do they might be subject to a security audit forbidding it. There's two reasons nonces can suck: first is that nonces may be passed around for 3rd party script usage and that blows a hole in your security policy, and the other is that many implementations to generate nonces are not implemented correctly, so the security team might have less trust in devs.
It really depends on the organization and project. Once you start getting near the security fence you may find it's more trouble than it's worth.
I would try to find less complicated solutions for small details like this. Obvious question might be why your CSS can't be a separate file that is small enough to not cause a performance issue.
<style nonce="sha256-Ce2SAZQd/zkqF/eKoRIUmEqKy31enl1LPzhnYs3Zb/I=">
html { background: red }
</style>
And a CSP like this default-src 'self'; style-src 'sha256-Ce2SAZQd/zkqF/eKoRIUmEqKy31enl1LPzhnYs3Zb/I='
Here's how I automate mine:https://github.com/uxtely/js-utils/blob/ad7d9531e108403a4146...
Built on Astro web framework
HTML: 27.52KB uncompressed (6.10KB compressed)
JS: <10KB (compressed)
Critical CSS: 57KB uncompressed (7KB compressed) — tested using this site for performance analysis.
In comparison, many similar sites range from 100KB (uncompressed) to as much as 1MB.
The thing is, I can build clean HTML with no inline CSS or JavaScript. I also added resource hints (not Early Hints, since my Nginx setup doesn't support that out of the box), which slightly improve load times when combined with HTTP/2 and short-interval caching via Nginx. This setup allows me to hit a 100/100 performance score without relying on Critical CSS or inline JavaScript.
If every page adds 7KB, isn’t it wasteful—especially when all you need is a lightweight SPA or, better yet, more edge caching to reduce the carbon footprint? We don’t need to keep transmitting unnecessary data around the world with bloated HTML like Elementor for WordPress.
Why serve users unnecessary bloat? Mobile devices have limited battery life. It's not impossible to achieve lighting fast experience once you move away from shared hosting territory.
It might improve time to first paint by 10-20ms, but this is a webpage, not a first-person shooter. Besides, subsequent page loads will be slower.
stevenpotts•4h ago
Feedback welcome, it's free for now.
promiseofbeans•2h ago
cAtte_•1h ago
al_borland•1h ago
jefozabuss•1h ago