移动端滑动卡片必须用JS监听touch事件实现弹性效果,因CSS scroll-timeline在iOS Safari、微信WebView和Firefox中完全不可用;需通过touchstart/touchmove/touchend计算位移并控制transform与transition,配合flex-wrap响应式布局及touch-action等细节优化体验。

移动端滑动卡片必须用 JS 监听 touch 事件,不能只靠 CSS
scroll-timeline 在 iOS Safari、微信 WebView 和所有版本的 Firefox 中完全不可用,@supports (animation-timeline: name) 在这些环境里直接返回 false。你写好 @scroll-timeline 规则后,在 iPhone 上连动画帧都不触发,控制台也无报错——它就静默失效。层叠滑动本质是“滚动位置 → 卡片位移 + 缩放 + z-index 重排”的链式响应,而 CSS 无法用变量绑定 z-index,也不能在 overflow: hidden 容器里可靠驱动多卡片层级变化。
弹性边缘效果要靠 transform + transition + touch 坐标差值计算
所谓“弹性边缘”,是指用户拖拽到边界时,卡片产生拉伸回弹感(类似 iOS 主屏),这必须基于手指位移量做实时 transform: translateX(),并在 touchend 后用 transition 回弹。纯 CSS 的 scroll-snap-type 只能硬停靠,不支持弹性阻尼。
- 记录
touchstart的clientX,在touchmove中计算横向偏移deltaX = currentX - startX - 限制最大拉伸量(如 ±40px),避免过度形变:
el.style.transform = `translateX(${Math.max(-40, Math.min(40, deltaX))}px)` -
touchend时判断是否超过阈值(如 20px)决定是否切换卡片,否则用el.style.transition = 'transform 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94)'回弹
响应式弹性布局需用 flex-wrap + min-width + gap,而非固定列数
移动端卡片宽度不能写死 33.33% 或 250px,否则小屏下溢出或留白严重。正确做法是让容器用 display: flex; flex-wrap: wrap; gap: 16px,卡片设 flex: 1 1 calc(50% - 16px)(双列)或 flex: 1 1 calc(33.33% - 16px)(三列),再配合 min-width: 280px 防止压缩过小。这样在 375px 屏上自动退为单列,428px(iPhone 14 Pro)可稳出双列。
注意:别用 nth-child 加边距做栅格,gap 已足够且不会在动态插入卡片时错位。
立即学习“前端免费学习笔记(深入)”;
真实项目中容易忽略的三个细节
一是 touch-action: pan-x 必须加在滑动容器上,否则 iOS Safari 会拦截横向 touchmove 做页面滚动;二是卡片内容区域要加 pointer-events: none(除按钮外),防止文字选中干扰手势;三是回弹动画的缓动函数得用 cubic-bezier(0.25, 0.46, 0.45, 0.94) 这类高弹性曲线,系统默认的 ease-out 回弹生硬,用户感知就是“卡住”。


















