问题
I've deferred non-critical CSS/JS and preloaded base CSS of the website. Every lab data on PageSpeed Insights have become better. Except "Largest Contentful Paint" and "Cumulative Layout Shift". Especially, the CLS increases from 0.002 to 1.148!
The images on the website are set as background-image
which I think there won't be "Images without dimensions" problem. I also tried to fix the font by using font-display
, but the CLS is still the same.
Are there any other techniques I can use to optimize the CLS?
回答1:
CLS Optimization
My answer addresses the second part of your question, regarding techniques that can be used to optimize CLS.
In broad terms, my solution hides the problematic elements in CSS, and makes them visible again in javascript. Layout shift is a problem - and contributes to the CLS score - only if if it is visible to the user; when it is invisible, it does not contribute to the CLS score. The detailed implementation is as follows.
First, create a class "antiCls" and add it to your custom CSS (in the HEAD element) as follows:
.antiCls {
visibility: hidden;
}
Next, add the following code to the end of your custom JS file (at the bottom of the BODY element). First, the JQUERY version:
$(document).ready(function(){
...
existing jquery code
...
$(window).on("load", function()
$('.antiCls').css("visibility", "visible");
});
});
Here is the vanilla javascript version, without jquery:
var cls = document.getElementsByClassName('antiCls'),
i = cls.length;
for (i = 0; i < cls.length; i++) {
cls[i].style.visibility = "visible";
}
Next, you need to identify the elements to which you will apply your new "antiCls" class. Under the Google "PageSpeed Insights" for the page, look under the section "Diagnostics", and expand the sub-heading "Avoid large layout shifts". There, you will find the offending (non-zero) DOM elements listed: these will probably be images, but other elements (including whole divs) may be listed there as well.
For images, apply the new antiCls class to the parent div, not to the image itself. For elements grouped together under one parent div, apply the new antiCls class to the parent div. Some experimentation will be required, but a CLS score of zero can usually be achieved easily using this technique.
Whether a CLS score of zero should be achieved is another question. To be effective, the antiCls class needs to be applied "above the fold" - that is, to elements that appear in the viewport without scrolling. It is important that at least some elements remain at the top to the page to which the antiCls class has not been applied: these elements will usually include a logo, and possibly some navigation. That way, the speed with which the user is presented with some critical content ("First Contentful Paint") won't be negatively effected.
In my own tests I have discovered that this CLS optimization technique makes no perceptible difference to the speed with which the page is displayed; meaning that a low or zero CLS score can be achieved at nearly zero performance cost.
回答2:
You need to inline your critical CSS.
Basically when the page loads it has to wait for all of your CSS to render the "above the fold" (everything immediately viewable without scrolling) content.
When you deferred all of your CSS you made that happen later so the HTML loads and then as your CSS loads the styles are applied, causing things to shift around on the page.
The key part of what it says is "defer non-critical CSS" needs deferring, "critical CSS" needs to load as early as possible.
What is critical CSS?
Critical CSS is all of the CSS required for the "above the fold" content.
What you do is add a <style>
element to your document <head>
and place all of the critical CSS in that.
That way the second all your HTML has loaded the browser also has all of the CSS it needs to render the page so it will render it almost instantly.
This is critical on a slow mobile connection as a large portion of load time on 3G / 4G is latency (round trip time to the server). Having the CSS required to render the initial page served as part of your HTML means there is only 1 request (your main page).
See this article which is quite good at explaining the concept
Please note this is not an easy task for most themes (locating the critical CSS is hard and most of the tools out there do not find all relevant styles) but is worth the effort if you are attempting to get super high initial load times.
This will fix your CLS as everything renders at once (so no layout shift).
The exception
You did mention you use background-image
as part of your CSS.
You either need to give that initial dimensions for the container that has the background image or use the Padding top CSS hack or similar to set the dimensions of the box first.
Otherwise when the image loads in it will cause a layout shift. These dimensions should be set in your critical CSS.
Final things
Please note this will fix Page Speed Insights.
However it doesn't mean all CLS in the real world is fixed. If you get problems with "field data" (real world data) showing large CLS after you fixed the "Lab Data" (simulated) you may have things lazy loading in too late further down the page etc.
It is beyond the scope of this question but bear in mind that CLS is measured until page unload in the real world, as mentioned in this explanation on CLS from Addy Osmani who works on Google Chrome.
来源:https://stackoverflow.com/questions/62928832/deferred-non-critical-caused-high-cls