how to hide html elements while waiting for all components to be loaded?
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 and 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 minimal 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 class="loading">
<main>show only when page is ready</main>
</body>
</html>
How can I prevent jank and reduce layout shift with responsive sized images?
I ended up using the solution found here:
http://davidecalignano.it/lazy-loading-with-responsive-images-and-unknown-height/#:~:text=And%20here%20is%20the%20formula,flashes%20on%20lazy%20loaded%20images.
HTML
<a class="thumb lazy-container" href="#">
<img class="lazy" data-original="image.jpg" alt="">
</a>
CSS
.lazy-container {
display: block;
position: relative;
height: 0;
}
.post .lazy-container {
padding-bottom: 55.3%;
}
.lazy-container img {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
Since all of my images have a different height, I put the padding-bottom percentage as an inline style for each image.
Set height of image with 100% width for CLS (Cumulative Layout Shift)
Best practice for images
A more universal way of doing what OP asked is to simply set a width and height on an image in pixels using the native width
and height
attributes.
This is what is advised as the modern best practice
Assuming that the browser has all the information it needs to calculate the width (from inlined CSS) modern browsers will then allocate enough space for the image to avoid a layout shift.
These width and heights do not have to be the actual size the image will display, just the correct proportions.
So in the below example we grab the width and height of the image thumbnail (say 640px wide and 480px high).
Then we set the width of the image in CSS relative to it's container (so in this example 50% of the page width).
The browser will then allocate the correct height for the image to avoid a layout shift. (in the below example it would allocate 720px height assuming the screen width is 1920px - a 960px wide image due to 50% width and then a height of 720px to retain the aspect ratio.)
$img = wp_get_attachment_image_src( get_post_thumbnail_id( $post->ID ) , 'thumbnail' );
$src = $img[0];
$height = $img[1]; //e.g. 640(px)
$width = $img[2]; //e.g. 480(px)
<style>
img{
width: 50%;
height: auto; /*this is important as otherwise the height set on the image will be used*/
}
</style>
<img src="<?php echo $src; ?>" width="<?php echo $width; ?>" height="<?php echo $height; ?>" />
Fiddle demonstrating
In the below fiddle I load a large image (you may still want to add throttling to see there is no layout shift). The space is automatically calculated by the browser so no layout shift occurs.
The big advantage is the below works with media queries (as you can set any width in the inline CSS) and will work correctly with a Content Security Policy as it doesn't rely on inline style
items.
<style>
img{
width: 50%;
height: auto;
}
</style>
<img src="http://picserio.com/data/out/369/sahara-desert-wallpaper_5757536.jpg" width="6400" height="4800" />
<p>I don't shift</p>
Related Topics
Twitter Bootstrap Radio/Checkbox - How to Put Glyphicon
What Is The Meaning of an Ampersand in Less Selectors
How to Center Text Inside: Before Pseudo Element
CSS - Horizontal Navigation List Items to Fill All Available Space
Is There an Equivalent of Spriting for Svg Images in Web Pages
Bootstrap: How to Create a Series of Div on One Line Hiding The Overflowing Divs
Align Flex-Box Items to Baseline of Last Text Line in a Block
How to Edit Auto-Formatting Rules for CSS/Scss/Less Using Prettier in Vscode
CSS- Target Text Links with Bottom Border on Hover, But Image Links with No Border
Applying a Clearfix to Nth-Child Without Additional Markup
Turn Off Animations in Capybara Tests
How Do Browsers Parse/Render CSS
CSS Selector to Check That Attribute Does Not Contain Both Values
Using Just CSS, Crop .Img Keeping Aspect Without Distortion
How to Show Red Border at Invalid Input Box After Clicking Submit Button with Angularjs