移动端单列滑动列表必须设 height 或 max-height,否则 overflow-y: auto 无效;需配 overflow-y: auto、-webkit-overflow-scrolling: touch(旧版 iOS),flex 容器须设 flex-direction: column,sticky 表头需父容器有 transform 或 will-change。

移动端单列滑动列表必须设 height 或 max-height
不设高度,overflow-y: auto 无效——这是最常被忽略的前提。浏览器默认让容器随内容撑高,滚动行为根本不会触发。你看到的“能滑”,其实是整个页面在滚,不是列表自己在滚。
正确做法是给列表容器(比如 <ul></ul> 或 <div class="list">)加显式高度约束:
<ul>
<li>用 <code>height: 300px(固定高,适合已知行数场景)
max-height: 70vh(更安全,适配不同屏幕,留出头部/底部空间)overflow-y: auto,且不能是 overflow: hidden 或未声明-webkit-overflow-scrolling: touch(iOS 15+ 已非必需,但旧版 WebView 仍依赖)
display: flex 垂直排列时别漏掉 flex-direction: column
很多人写 display: flex 就以为自动单列,其实默认是 row(横向)。移动端列表要垂直堆叠,必须显式声明方向:
-
flex-direction: column才能让<li>或子项从上到下排列 - 如果同时用了
flex-wrap: wrap,反而可能在窄屏折成多列(尤其当子项设了flex-basis) - 用
gap: 12px控制项间距,比margin-bottom更可靠——不会因最后一项多出空隙 - 避免对子项设
width: 100%:flex 容器中它常冗余,还可能和flex-grow冲突
用 position: sticky 固定表头时,父容器需 transform 或 will-change
想在列表滚动时让标题栏(如 <h3>联系人</h3>)始终可见?直接加 position: sticky; top: 0 不一定生效。原因在于:sticky 的“容器边界”由最近的具有变换属性(transform、perspective、filter)的祖先决定;若没有,就回退到 viewport,导致粘性失效。
立即学习“前端免费学习笔记(深入)”;
- 给列表外层容器加
transform: translateZ(0)或will-change: scroll-position - 确保 sticky 元素的父级没设
overflow: hidden(会截断粘性效果) - 不要在 sticky 元素上设
margin-top:它会把“粘住位置”往下推,造成视觉错位 - Android Chrome 早期版本对
sticky支持不稳定,可降级用 JS 监听scroll+getBoundingClientRect()模拟
滑动区域内部避免 white-space: nowrap
单列列表里若含长文本(如手机号、地址、URL),加了 white-space: nowrap 会导致整行横向溢出,用户必须左右滑才能看全——这违背“单列垂直滑动”的初衷。
- 默认用
white-space: normal(浏览器默认值),允许自动换行 - 对特别长的字段(如 Base64、JWT),用
word-break: break-all或overflow-wrap: break-word - 禁用
text-overflow: ellipsis在非末尾项:它需要width+overflow: hidden,而 flex 子项宽度不可靠 - 若需截断,优先用 JS 计算字符数后截取,再加 “…” 后缀,语义更清晰
真正难的不是让列表能滑,而是让滑动过程不卡、不跳、不遮挡、不误触。尤其是 sticky 头部与 touchmove 事件共存时,iOS 和 Android WebView 对合成层的处理差异很大,建议在真机上测至少三种主流机型,别只信 Chrome DevTools 的模拟器。



















