1

I have a button to pull some data from backend. But the length of the data is uncertain and the time to load is also uncertain.

This will generate high CLS penalty. Is there anyway to avoid this?

var stHandler = 0;
$('#render').click(function(){
  clearTimeout(stHandler);
  $('#result').html('loading...');
  // [Simulate the server response time]
  // CLS will not be penalized if the everything happens in 100ms,
  // but most of the case, the server will return the data longer than that
  stHandler = setTimeout(function(){
    $('#result').html(fakeResultBuilder);  
  }, 500 + Math.random()*1000);
  
})

// [Simulate the real-world condition]
// Every time you load this content, the height will be different.
function fakeResultBuilder(){
  var html = '';
  for (var i=0; i<Math.random()*100; i++) {
    html += '<div class="block"></div>';
  }
  return html;
}
button {cursor:pointer}
.block {height:10px; background:#f00; width:20px; margin:5px}
#result {border:1px solid #999}
footer {margin-top:1em}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<button id="render">Render</button>
</div>
<h2>Result:</h2>
<div id="result"></div>
<footer>Page Footer - will have huge CLS sometimes</footer>
AGamePlayer
  • 7,404
  • 19
  • 62
  • 119
  • Can you put the footer at some well-defined static position (e.g. bottom of the screen)? Can you at least estimate the height of fetched dynamic content (say, whether it'll be 5vh, 50vh or 150vh)? – STerliakov Jan 07 '23 at 05:02
  • No, actually there is much more content than just a footer. :( – AGamePlayer Jan 07 '23 at 11:27

1 Answers1

0

The key is to adjust as much as possible within the 500ms grace period (note not 100ms as given in your code comment). The 500ms grace period is set because clicking on things (like your Render button) is an expected shift. However, if it happens considerably later (and 500ms is set as the limit) then it's back to being an unexpected shift. The user may be in the middle of reading some of the footer while they wait.

While the full response may not be able to be returned within that 500ms, you can still reserve some space (perhaps using min-height?) to, at the very least, reduce the CLS. The default height of an empty div is 0px so ANYTHING you do here will be better than than that as surely it will be larger than 0ms?

Additionally if it's enough to always knock the footer off-screen then adding a minimum height to push that footer off screen will mean any further moves for it are not considered CLS.

This may leave a large white space, which may not be ideal, so you may wish to consider some kind of "Loading..." message or a loading spinner. This will give an indication that something is happening to the user rather than them being unsure and perhaps rage-clicking the render button again and again.

Barry Pollard
  • 40,655
  • 7
  • 76
  • 92
  • Thanks for your informative reply. Actually my users are happy with the experience because I have a loading animation there so they have the expectation to wait. But Web Vitals will not take that into the consideration. It will count the time and if it takes too long, your CLS score will be very poor. Is there any way to tell the web vitals monitor behind all this not to penalize this design? – AGamePlayer Jan 09 '23 at 12:20
  • No, there is no way to get exceptions for sites. Core Web Vitals are, by design, supposed to be measurable and comparable across websites. Although you may have a loading animation, that may still not prevent the negative UX of any unexpected shifts. For example they may be scanning your footer links while they wait and boom they are shifted out of the way when the load finishes. – Barry Pollard Jan 09 '23 at 16:14
  • I see. Thanks for the answer and confirmation. So this is not a development issue but a design issue. I have to re-design the product to fix CLS penalty in this case. – AGamePlayer Jan 10 '23 at 07:19