DEV Community

Cover image for Fixing Cumulative Layout Shift
Ben Halpern
Ben Halpern

Posted on

Fixing Cumulative Layout Shift

Cumulative layout shift is the term that refers to content that jumps after initial load.

Not only is CLS frustrating for users, it will also become more important for SEO purposes this year. Of course those things are connected. Because it is such a big user experience problem, Google Search rankings will be cracking down on this.

cls

We have a few existing CLS issues within Forem. Google shows us about this through the Search Console within the Core Web Vitals tab:

Google dashboard

Yellow in this graph represents pages that need work.

"Need work" means it is a small issue. It certainly isn't a giant ad popping up in our face, but it is still frustrating and possibly jarring.

This is what they were talking about:

blip

This happens because we load the comment reaction number asynchronously so we can cache the underlying HTML.

... And this was the fix...

Improve cumulative layout shift on comment reactions + optimizations #12309

What type of PR is this? (check all applicable)

  • [x] Refactor
  • [ ] Feature
  • [x] Bug Fix
  • [x] Optimization
  • [ ] Documentation Update

Description

Cumulative layout shift refers the sudden jump of elements on a page when any change happens after initial render.

Details here: https://web.dev/cls/

This is not only a bad experience for users, Google has warned that this will become a bigger ranking factor:

Details here: https://www.searchenginejournal.com/cumulative-layout-shift/371946/ https://www.popwebdesign.net/popart_blog/en/2020/09/cumulative-layout-shift-how-to-rank-on-google-in-2021/

I'm not sure it is covered in that post, but I believe Google announced they will step up how much this matters in May 2021.

In general this is a great thing for Forem because we already prioritize user experience and have minimal CLS issues, however, we do have some.

This PR addresses this one:

https://user-images.githubusercontent.com/3102842/104824544-a24bb380-5820-11eb-8362-8e48dd8ed405.mov

Upon loading the page, we asynchronously fetch the number of reactions in the comment trees. This is nice so that we don't have to bust the whole page every time a reaction is made, however as currently implemented, it causes a CLS.

In examining the ways to address this, I believe the best route is what I have chosen to do:

  • We include the current public reactions count inline, knowing it may be cached, and use the async fetch as a way to adjust the reactions. This will improve UX, as most of the time there will be no jump at all, and if the reaction count has changed recently it will act as a small adjustment, say from 7 to 8 reactions.

As Forems grow (like DEV), they have great potential to become a knowledge base. That means that some old threads can stick around to be useful for a long time. However, over time, posts are less likely to have new reactions popping up every few minutes.

This PR takes advantage of this and reduces that async query we make when there has been no new comment activity for a week. That is to say: We do not fetch new async reaction numbers for posts nobody is commenting on anymore. This will reduce one request for many posts.

Related Tickets & Documents

https://github.com/forem/forem/issues/12310

QA Instructions, Screenshots, Recordings

Please replace this line with instructions on how to test your changes, as well as any relevant images for UI changes.

UI accessibility concerns?

This should only improve possible issues.

Added tests?

  • [x] Yes
  • [ ] No, and this is why: please replace this line with details on why tests have not been included
  • [ ] I need help with writing tests

Added to documentation?

Generally the way to deal with CLS is to make space for content that may load asynchronously before it loads. There are a few ways this could have been dealt with. In this case I deemed that it was reasonable to first include the cached number instead of nothing, and then if the number updates a few milliseconds after load.

If it was not possible to modify the code such that we could include the number, it would likely suffice to include a blank HTML element that takes up the approximate space for most like numbers.

Top comments (7)

Collapse
 
simonholdorf profile image
Simon Holdorf

Hey Ben, thanks for the insights. I have comparable issues on The Smart Coder but managed to push them into the back of my head successfully. Guess I'll have to start dealing with it soon...so thanks again :D

Collapse
 
marcelcruz profile image
Marcel Cruz

Thanks for sharing this, especially now that CLS has a bigger SEO impact.

By the way, where in the Search Console you find those URL reports? Thanks!

Collapse
 
ben profile image
Ben Halpern

Core Web Vitals tab. I update the post for more clarity here.

Collapse
 
marcelcruz profile image
Marcel Cruz

Thank you Ben!

Collapse
 
cwraytech profile image
Christopher Wray

That is helpful. Could you also do a min-width property in css, or would Google not like that?

Collapse
 
aspiiire profile image
Aspiiire

Wow thats amazing, thanks for saving my website before it goes online, first time that i hear about CLS and SEO, thanks for sharing

Collapse
 
heyrohit profile image
Rohit Gupta

🙏 well that was a great post.