Fixing Cumulative Layout Shift

ben

Ben Halpern

Posted on January 19, 2021

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.

💖 💪 🙅 🚩
ben
Ben Halpern

Posted on January 19, 2021

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related