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.
We have a few existing CLS issues within Forem. Google shows us about this through the Search Console within the Core Web Vitals tab:
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:
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?
- [x] Developer Docs and/or Admin Guide
- [ ] README
- [ ] No documentation needed
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)
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
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!
Core Web Vitals tab. I update the post for more clarity here.
Thank you Ben!
That is helpful. Could you also do a min-width property in css, or would Google not like that?
Wow thats amazing, thanks for saving my website before it goes online, first time that i hear about CLS and SEO, thanks for sharing
🙏 well that was a great post.