CSS 与布局 / 📜 Scroll · 滚动怎么动、长什么样、装得下多少 待审核 9 页

📜 Scroll · 滚动怎么动、长什么样、装得下多少

滚动这件事有三个面。第一面是滚动怎么动:滚到尽头多余的滚动量去哪、跳转是瞬移还是平滑、斜向手势的另一维分量保不保得住、上方内容变高时画面跳不跳、松手后停不停得整齐——这些由几个常被忽视的 CSS 属性声明式地决定,各自只有两三个取值,用对了能消除一整类恼人的体验问题。

第二面是滚动条本身长什么样:从 CSS 换肤,到隐藏原生用 DOM 自绘,再到 Canvas 整条画——代价与能力递增。

第三面是滚动装得下多少:当数据大到十亿、万亿行,一次性渲染与加载都不可行时,虚拟滚动如何只渲染可见的几十行、只取看过的数据,还能绕过元素高度上限滚得动。

本系列每页讲一个属性 / 一族属性 / 一种做法,配一个可以直接拖动、点击的 demo,在你浏览器里跑真实行为。

快速选型: 弹层 / 聊天框滚到底别带动背景、移动端关掉下拉刷新 → overscroll-behavior;点目录 / 回到顶部要平滑过渡 → scroll-behavior;地图 / 无限画布 / 宽表要斜着拖而不走楼梯 → scroll-axis-lock: none;要在程序滚动停下后再接动画 / 判断有没有被打断 → await scrollTo();图片加载导致正在看的内容乱跳 → overflow-anchor;carousel / 整屏分页要停得整齐 → scroll snap;sticky 贴顶变身 / 吸附点亮 / 边缘渐隐这类「看滚动态换样式」→ scroll-state 容器查询;想换滚动条外观、做进度条 / 章节刻度式滚动条 → 自定义滚动条;十万行以上的长列表 / 大表卡顿 → 虚拟滚动。

滚动怎么动 · 行为

这一类属性不改滚动条长相,只管滚动的动作本身:溢出的滚动量去哪、跳转瞬移还是平滑、上方变高时画面跳不跳、松手后停不停得整齐,以及让样式直接读出容器此刻的滚动态。

overscroll-behavior · 传播与回弹

overscroll-behavior:滚到底之后,溢出的滚动去哪

一个属性同时管滚动传播与边界回弹两件事,auto、contain、none 加上新增的 chain 正好填满一张 2×2 表。

scroll-axis-lock · 轴锁

scroll-axis-lock:轴锁与对角滚动

触屏与触控板上斜向拖动,浏览器会把手势投影到位移较大的那条轴,另一维分量整段丢弃,路径走成楼梯。这条启发式挡的是阅读流里的误漂,代价落在地图与无限画布这类二维界面上。scroll-axis-lock: none 关掉它。

scroll-behavior · 平滑

scroll-behavior:让跳转滚动从瞬移变平滑

程序触发的滚动默认瞬移,scroll-behavior: smooth 给它加平滑补间。它只管程序滚动,用户拖动永远即时。

scrollTo() Promise · interrupted

scrollTo() 返回 Promise:等程序滚动停下再动手

平滑滚动一直缺一个「何时到位」的信号。新版 Chromium 里 scrollTo() 返回 Promise,滚动停下时兑现 interrupted。

overflow-anchor · 锚定

overflow-anchor:上方内容变高时别让画面乱跳

上方内容变高时浏览器会悄悄调 scrollTop 把当前内容留在原地。overflow-anchor 就是这套默认补偿的开关。

scroll snap · 吸附

CSS Scroll Snap:让滚动整齐地停靠

容器定轴与强度、子项定对齐点、padding 与 margin 微调落点。再到纯 CSS 的圆点指示器与翻页按钮。

scroll-state · 容器查询

scroll-state:让样式读出容器此刻的滚动态

scroll-state 容器查询让 CSS 直接问「贴顶了吗、吸附了吗、还能滚吗」,三类反馈不再需要监听 scroll。

滚动条长什么样 · 外观

另一面是滚动条本身的样子。从 CSS 换肤到 DOM、Canvas 自绘,三档递进地把滚动条的外观与交互逐步接管。

::-webkit-scrollbar · DOM · Canvas

三种自定义滚动条的方式

换皮肤、接管交互、整条自绘三档递进:CSS 伪元素只改外观,DOM 自绘拿回交互,Canvas 换取阻尼动画与复杂可视化。

滚动装得下多少 · 海量数据

前两面都还在样式与交互行为的范畴。第三面是工程问题:当数据本身大到十亿、万亿行,一次性渲染与加载都会崩,虚拟滚动如何用切片、懒加载与滚动条缩放,只靠原生能力把它滚动起来。

virtual scroll · table slice · infinite pixels

虚拟滚动:在浏览器里滚动十亿行

只渲染可见行、只物化滚过的数据、总高超过元素上限时按比例缩放滚动条——把千万行表格塞进一个视口。

🔗 相关链接

📐 行为 · 规范 / MDN

🎚️ 外观 · 自定义滚动条

📦 海量数据 · 虚拟滚动

🎮 玩一玩 / 灵感

为什么值得专门认识它们: 「行为」这四件事过去多半要靠 JS 监听 scroll 反复计算来勉强实现(手动拦传播、手写补间动画、手算 scrollTop 防跳、手动吸附),既抖又难维护;如今浏览器把它们做成了声明式 CSS 属性,代码更短、手感更稳。而滚动条「外观」反过来——能换肤的标准属性有限,真要做复杂可视化滚动条,仍得退回 DOM / Canvas 自己接管。到了「海量数据」这一面则更靠工程而非单个 CSS 属性:虚拟滚动把渲染、加载与滚动条高度三件事各自从「随行数线性增长」压成常数。