最佳实践:没有布局偏移的无限列表

发布日期:2021-07-09
今天,鸽将通过一些好办法来看看优化加载长列表来提高网站核心性能。
 
无限长的列表是一种加载策略,在用户向下滚动页面时获取和呈现新内容。一般来说,页面上不需要显示加载更多按钮,也不需要显示下一个链接。获取更多内容是当用户滑动到页面底部的时候自动进行的。
 

A comparison of infinite scroll vs. pagination vs load more

这种模式已经在社交媒体平台例如Facebook和Twitter等应用程序上很常见。在Twitter上,当你向下滚动时,会加载更多的tweet。它是一种分页类型,不涉及导航,而是观察滚动位置。一旦它们到达页面的边缘,将获取下一批tweets。无限滚动网站的主要好处是,它允许用户保持参与和不断浏览。有人可能会说,这种模式也鼓励了无休止的滚动。今日头条等信息流软件也都采用这种模式推荐读者感兴趣的内容,让你欲罢不能。

分页

就用户体验而言,将站点内容或搜索结果分成页面仍然是最流行的策略。分页给了我们一个特定位置的感觉(一个URL)和一个选择只是去哪里下一步。这是一个很好的模式,可访问性,搜索引擎优化和广泛使用。因为分页需要点击才能跳转到下一页,所以有人认为与移动设备上无限滚动相比,分页更容易阻碍用户粘性,但实际情况可能有所不同。
 

加载更多

“加载更多”是分页和无限滚动的混合体。用户必须单击或点击加载更多按钮才能加载新内容。它给用户一种控制内容的感觉,有更多的逻辑中断。它还可以让用户在决定加载更多内容之前暂停在页脚。无限滚动和加载更多会导致布局变。如果列表下面有内容,比如页脚,这时候会出问题。在许多实现中,无限滚动会让用户很难到达页面的页脚。因为它不断将内容往下推,它可能导致布局变化。事实上,这是其中一个主要的无限滚动设计挑战:随着项目不断加载用户到达底部的列表,用户可以看到页脚。然后一两秒后加载新的结果会让页脚内容消失。
 

Layout Shifts from infinite scroll

在页脚中有时会包含链接列表、实时聊天对话框或社交媒体对话框,但随着这些内容不断被向下滚动,它可能会让你的累积布局Shift得分更低。这也可以看到在加载更多的网站如果内容是在页脚。下面是一个真实世界的例子,由于无限滚动页脚布局变化:如果你还没有预留足够的空间为下一个项目(或预取的这些物品)提前无限只列出你曾经滚动下来,发现有一个时刻,你点击窗口的底部,它“弹出”当新内容已经被拿来和附加吗?通过不提前(pre)获取内容,或者至少使用容器或占位符为下一组行保留空间,有可能会对页面周围或页面下方的元素引入令人惊讶的变化。下面是一个使用无限滚动的Facebook.com feed的真实例子。虽然它为新内容创建占位符,但这些占位符对于它们包含的最终内容具有不同的维度。布局发生变化是因为没有提前为新卡预留足够的空间:

下面,我们可以使用Chrome DevTools > Performance panel > Experience来识别有助于布局变化的元素。正如所怀疑的,它们是靠近视口边缘的卡片:

DevTools displaying layout shifts for the cards on Facebook.com's timeline feed

 

累积布局位移

需要强调一下,累积布局移位(Cumulative Layout Shift, CLS)是一个核心Web重要指标,用来测量当页面上的元素改变其起始位置时,viewport中发生的布局变化。像Chrome这样的浏览器目前在CLS中考虑的唯一特例是,如果有用户输入,我们认为500ms内是允许用户发起布局变化,这将被排除在评分计算之外。
无限滚动和加载更多按钮都可能对布局模式进行转变。如果内容(如页脚)被推下来,它将考虑在页面上的如果它花费的时间超过500 ms从用户点击按钮的时候物品已经准备好被显示。
注意:“无限滚动”和“加载更多”只是两个模式的例子,其中内容是根据用户输入动态注入的。这些内容有时需要往返于服务器、处理或其他可能超过累积布局移位“输入到移位”阈值的延迟。这样的页面应该将响应时间优化到允许的阈值以下。如果延迟是可以预见的,那么就尽可能为新内容保留足够的空间,然后在内容加载时填充它。
由于技术原因,这500ms的要求可能很难满足,除非无限滚动或加载更多实现实现如下所示之一。
 

如何避免无限滚动的布局变化?


为获取任何动态内容预留足够的空间(例如大小合适的占位符)是至关重要的。不这样做可能会导致布局变化。这适用于页面Document生命周期中可能使用的任何UX模式。
像无限滚动这样的模式可能会随着时间的推移而改变布局。在新的动态内容呈现到视口之前,尝试为任何骨架UI(如卡片)保留足够的空间,以最小化这对向下移动其他可见内容的影响。如果您的用户喜欢无限滚动,我们不建议删除它只是为了优化CLS,但应确保预留足够空间。
 
如果使用无限滚动或加载更多内容,鸽会考虑以下三个主要技巧:
  1. 在用户滚动到页面的那一部分之前,为可能加载的内容保留足够的空间。这可以通过多种方式实现,包括通过Skeleton placeholder为可能需要获取数据才能呈现内容的内容。
  2. 删除页面底部的页脚或任何可能被内容加载下推的DOM元素。这限制了对CLS的影响。
  3. 为页面下的内容预取数据和图像,这样当用户滚动到那一步时,它就已经存在了。这种方法更加复杂,但不仅仅是为下一组内容保留空间,因为很可能已经获取了这些内容。

是否有简单有效的方法来实现无限列表?

鸽认为,最简单的长列表显示方式是单独创建一个虚拟层。让这个层浮动在内容层上。这个层主要用来显示无限列表。这样做的好处是,这个层可以很精准的控制只显示最近的列表项而不是一个完整的列表。想一下,假设用户往下拖动了1000次,每次加载20个新内容,难道我们要放20000个列表项在页面上么?虚拟层是固定,虚拟层下也不能显示任何其它内容。