Cumulative Layout Shift with Bootstrap 4 Grid

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



Leave a reply



Submit