piapia123
zh

滚动吸附生成器

样式

所有处理都在浏览器本地完成,数据不上传服务器

实时预览改上面的参数,这里立刻跟着变
CSS 代码

滚动吸附让「松手之后停在整张卡片上」这件事不用写一行 JavaScript。选好方向与对齐方式,下面那块可以直接拖动看效果。 ⚠️ 它要两个元素配合,这是最常被漏掉的一点: `scroll-snap-type` 写在容器上,`scroll-snap-align` 写在子项上。只写一半,滚动起来就是普通滚动 —— 而「什么都没发生」是最难查的症状:不报错,两个属性单独看也都写对了。 ⚠️ `mandatory` 与 `proximity` 的区别值得想清楚: · `mandatory` 一定停在某个吸附点上。内容比容器长的时候,浏览器会强制回弹 —— 用户看不到中间的部分,而屏幕上没有任何提示告诉他下面还有东西。键盘翻页也会跳着走。 · `proximity` 只在滚得够近时吸附,其余时候自由滚动。 所以默认给的是 `proximity`:长内容用它更安全,而「差一点点也吸附」这个体验差别通常不值得拿「部分内容看不到」去换。 ⚠️ 另外,触摸设备上滚动吸附的体验与鼠标不同(惯性与吸附的配合方式不一样),预览只能代表鼠标下的表现。

功能

  • 四个方向:横向、纵向、两方向、跟随书写方向
  • 三个对齐位置:起始边、居中、末尾边
  • ⚠️ `proximity` 与 `mandatory` 的区别写在提示里,并说明 `mandatory` 在长内容上的问题
  • ⚠️ 说明两个属性必须配合:`scroll-snap-type` 在容器、`scroll-snap-align` 在子项,少一半不会报错
  • 实时预览可以直接拖动
  • 纵向时容器自动带高度(不给高度就滚不动)
  • 复制的是容器与子项两段,选择器可直接改名

使用方法

  1. 选吸附方向与对齐位置
  2. 在下面那块上拖动,看吸附的效果
  3. 复制代码,把容器与子项两段分别套到自己的结构上

常见问题

为什么我写 scroll-snap-type 没效果?
多半是少了另一半。滚动吸附需要容器与子项配合:`scroll-snap-type` 写在滚动容器上,`scroll-snap-align` 写在每一个要吸附的子项上。只写容器那一半,滚动起来完全正常 —— 就是普通滚动。这是它最难查的地方:没有报错,两个属性单独看也都写得对,而表现是「什么都没发生」。另一个常见原因是容器没有可滚动的溢出(内容比容器短,或者没给容器尺寸),那种情况下吸附自然也无从谈起。
mandatory 和 proximity 该选哪个?
默认选 `proximity`。 `mandatory` 的承诺是「一定停在吸附点上」,听起来更好,但内容比容器长的时候浏览器会强制回弹 —— 用户滚到中间松手就会被弹回去,于是中间那部分内容根本看不到。而屏幕上没有任何东西提示他下面还有内容。键盘用户翻页时也会一个吸附点一个吸附点地跳。只有在内容每一屏都刚好是一个吸附项(典型的轮播:每张卡片正好占满)时,`mandatory` 才是安全且更好的选择。
为什么纵向吸附要专门给高度?
因为一个没有高度约束的块不会滚动 —— 它的高度由内容撑开,永远等于内容高度,于是没有可滚动的余量。横向同理(不给宽度时它会一直往右长)。所以纵向吸附几乎总要配一个 `height`(或者 `max-height`),这也是它比横向更容易写错的地方:横向滚动容器在普通文档流里宽度天然受限,纵向的则不是。
滚动吸附会影响键盘和屏幕阅读器吗?
会影响,而且 `mandatory` 的影响更明显。键盘用户按 `PageDown` 或方向键滚动时,强制吸附会让他们跳过一个又一个吸附点,读不到中间的内容。屏幕阅读器把内容按 DOM 顺序读出来时不受吸附影响(吸附只是视觉上的),但视觉与朗读的顺序不一致本身就会让人困惑。规范里为此提供了 `scroll-snap-stop: always`(每个吸附点都必须停),但更稳妥的做法是长内容改用 `proximity`。CSS 没法替你做这个判断。
轮播图该用滚动吸附还是 JavaScript?
优先用滚动吸附。 它免费带来几件 JavaScript 版本往往做不好的事:触摸板与触屏的原生惯性、键盘方向键滚动、滚动条、以及「浏览器的后退按钮能回到上一个滚动位置」。而且它没有脚本就意味着不会因为脚本加载失败而整个失效。JavaScript 只在需要额外的东西时才值得上:自动轮播、无限循环、把当前页同步到指示点、或者需要在吸附结束时做别的动作。这时候也是先有滚动吸附、再用脚本去读它的状态,而不是自己重写一套滚动。

相关工具