返回列表需恢复滚动位置
别名: 列表滚动恢复 · scroll restoration · 返回不回顶 · history scroll
概念解释
从列表点进一条再返回,人期望视口仍停在离开时的那一带,而不是被放回第一条。scroll restoration(滚动位置恢复)在这里是往返的基本礼貌:列表还是那份、顺序没被当成问题,只要求「不要让我从头再翻一遍」。浏览器对普通多页文档默认就会尝试恢复滚动;单页应用若把列表当新页面挂载,这个默认就丢了。
这条只管「回来时不要回顶」。列表在离开期间插了新项该按哪一条对齐、无限列表要先加载多少才能对上,是更硬的恢复问题,不在这里处理。
机制
人用空间记忆给列表做书签:刚才停在「大约三分之二、那张蓝色卡片附近」。返回若从顶开始,书签作废,已经付出的扫描被强制重演。代价随离开前滚过的距离上升,短列表不明显,一屏以上就开始愤怒。History API 的 scrollRestoration 把偏移记在会话历史上,整页重载时还能对上;SPA 路由只换 DOM、不换文档,浏览器以为没有滚动过,偏移是 0。列表组件若在进入详情时卸载,回来第一帧渲染的是初始高度,即便稍后去设 scrollTop,人已经看见了顶部。
所以基本恢复有两步:记住离开时的偏移(或锚点附近的像素位置),回来第一帧就落到那里,而不是先画顶再跳。它假设列表的内容和顺序大体还在——这是「基本」的前提。
怎么研究
进出任务:在至少滚过一屏的列表上打开一项,返回,量视口是否仍覆盖离开时的区域。
- 自变量:实现(浏览器默认 scrollRestoration / SPA 卸载后重挂 / 手动 scrollTo)、列表长度。
- 因变量:返回后与离开前的像素差、是否先出现顶部、重新向下滚的距离、口头把返回描述成「被扔回去」。
- 方法论注意点:只测短列表会得到「回不回顶无所谓」。必须在离开前滚过一屏以上。不要在离开期间往列表里插新项——那会把基本恢复和「内容变了该怎么对齐」混成一个失败,后者要分开测。
边界
列表本来就不足一屏,回顶和恢复无法区分,这条没有可观察差异。用户在详情里点了「回到列表顶部」一类的显式动作,是主动放弃当前位置。筛选或排序在离开期间被系统改掉,列表已经不是离开时那一份,只恢复像素会停在无意义的空白,这时该先承认列表变了,而不是死保偏移。搜索结果被重新查询后条数大变,同样不再适用「还是刚才那一带」。
怎么落地
- 离开列表时把当前滚动偏移和会话历史绑在一起;返回时在第一帧恢复,禁止先渲染顶部再
scrollTo。 - SPA 对返回栈上的列表做保活或缓存滚动值;不要在每次进入列表路由时从
scrollTop = 0起。 - 多页文档打开
history.scrollRestoration = 'auto',不要全局关掉之后又忘记自己补。 - 验证:在桌面和手机上各找一份超过两屏的普通分页或有限列表,进详情再返回。录屏里只要出现顶部停留超过一帧,或人开始往下找刚才那条,就是失败。不要用会在离开期间自动插新项的信息流做这一条的验收。