nuxt.com
nuxt.com copied to clipboard
perf: improve css render performance
The Problem
The page has hight render time especially for recalculate styles layout also paint is not optimal.
Steps to reproduce
- Visite https://nuxt.com/modules as it is a good candidate to quickly test it.
- As I'm on a MacBook Pro M2 Max I used 4x throttling to emulate more commonly used devices
- Hit the toggle dark mode button a couple of times in a row
You should see a heavy delay in responsive ness due to heavy recalc and layouting.
Measurement
Desktop unthrottled
Desktop 4x throttled
Mobile unthrottled
Mobile 4x throttled
Solution
Use CSS techniques that improve rendering
Poc
To get quick insight how the changes improve rendering I used source overwrites in the Chrome DevTools.
Here the used snippet:
/* Contain and content visibility */
img, svg, span[class^="i-ph"] {
contain:content;
}
header > div {
contain:size;
}
#smooth > div:nth-child(2) div.grid > div,
footer h3, footer li,
span[class^="i-ph"] {
content-visibility: auto;
}
#smooth > div:nth-child(2) div.grid > div {
intrinsic-sice: 238px;
}
footer h3, footer li {
intrinsic-sice: 18px;
}
span[class^="i-ph"] {
intrinsic-sice: 20px;
}
/* Mobile/Tablet */
#smooth > div:first-child {
display: none;
}
This PR includes
style adoptions as well as adding img lazy loading in the following files:
- index
- components:
- AppFooter
- AppHeader
- blog
- slug
- index
- enterprise
- job
- sponsors
- modules
- slug
- index
Measurement before/after 4x throttled
Mini map comparison
Mini map comparison inc CWV plugin
Im happy to adjust/move code around as I am not really familiar with the code base and assume the location of the code could be improved...
All theory on the improvements can be found here: https://github.com/push-based/css-contain-and-content-visibility-research
Okay, let's see how we do that:
Tailwind does not provide utils for contain (yet, sent a PR https://github.com/tailwindlabs/tailwindcss/pull/12747) and also not for content-visibility (not planned so far because of browser support I suppose 🤷). Thus, the easiest would be creating plugins for both in the tailwind config. An example is already present in the tailwind docs for content-visibility and feel free to copy from my PR linked above.
These changes have to go into the tailwind.config.ts.
For contain-intrisic-* (e.g. contain-intrinsic-size), a plugin would be neat too but also a little bit more work as the utils wouldn't be static. Thus, arbitrary values in Tailwind would be the easiest. See the docs + this playground as example.
For the "more specific CSS" - I wonder if we either could fix this straight away in the UI library.
If you want to set it globally though, it might make sense to add an own assets/css/tailwind.css and define global styles there 👍
img, svg, span[class^="i-ph"] {
contain:content;
}
span[class^="i-ph"] {
content-visibility: auto;
contain-intrinsic-size: 20px;
}
For pages/modules/index.vue, it would work the same 👍
Let me know if you have any questions
Excellent description! 😍 Helps a lot.
Thx for your time! 🙏 Will see what I can do...
Any thoughts @benjamincanac?
I'm not familiar with those CSS properties so I won't be much of a help but I agree with @manniL's review to improve how those properties are defined using a plugin / arbitrary values.
@BioPhoton Do you plan to make the changes?
Hi just saw it. I'll push what I have tomorrow afternoon latest 🙌