chromium lighthouse tells me :
performance 89
(orange)
Cumulative Layout Shift 0.388
(red alert !)
Avoid large layout shifts
html :
<html>
...
<body >
...some static elements
</body>
...
</html>
css :
body.loading * { display : none; }
js when DOM is loaded :
document.addEventListener('DOMContentLoaded', (e) => {
//do many dynamic stuff with the DOM depending on user data (& register events listeners)
})
& finally when everything is in place in the dom, through window.onload
(or if that event comes too soon, a callback once everything is in place) :
document.body.classList.remove('loading')
If I remove the loading
class from the html lighthouse says great perf 100.
I thought before seeing this lighthouse analysis that my layout was shifting from a simple loading (css) animation to a completely ready page with no visible changes of the dom for the user during the load so i assume now that i am wrong, doing something wrong & missing something.
How should i do that instead for optimal loading while not risking having elements that are not ready ever being displayed ?
CodePudding user response:
I was waiting to put a bounty but it turns out that now lighthouse doesn't flag for CLS anymore although i didn't make any changes there (on the opposite i've added some code in html, css & js that should have made the page slower... ??)
so answer is (at least until being proven otherwise) :
Hiding elements while the page is loading & javascript is not ready doesn't have negative impact on performance.
here is minimalist code to have a ultra light spinner while the page is not ready yet
const MyOnLoad = function() {
setTimeout(function(){ // only for the sake of displaying here the spinner 2 and half second obv
document.body.classList.remove('loading')
}
,2500)
}
window.onload = MyOnLoad
.loading {
margin: 34vmin auto;
border: 0;
border-radius: 50%;
border-top: 0.89vmin solid red;
width: 21vmin;
height: 21vmin;
animation: spinner 2s linear infinite;
}
@keyframes spinner {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.loading * {display: none;}
<html>
<body >
<main>show only when page is ready</main>
</body>
</html>