滚动容器需设固定max-height和overflow-y: auto,用::before/::after加linear-gradient阴影;JS监听scroll事件可动态控制阴影显隐,但纯CSS方案更稳定。

滚动容器必须有明确的 overflow 和高度约束
没有显式 height 或 max-height,且 overflow-y: auto 未生效时,阴影根本不会触发——浏览器压根没产生滚动。常见错误是只写 overflow-y: scroll 却让内容自然撑高,此时滚动条永远不可见,::before/::after 伪元素也就无从谈起。
实操建议:
- 给容器设固定
height或max-height,例如max-height: 400px - 必须声明
overflow-y: auto(不是scroll,避免 Chrome 下始终显示空滚动条) - 确保子元素总高度 > 容器高度,否则不滚动,阴影不出现
用 ::before + ::after 叠加渐变遮罩实现“可感知”的阴影
CSS 本身没有“滚动到顶/底时自动加阴影”的原生机制,只能靠伪元素盖在容器边缘,用 linear-gradient 模拟渐隐效果。关键在于:阴影只是视觉提示,它不随滚动位移,而是固定在容器上下边界。
示例结构(假设容器类名为 .scroll-list):
.scroll-list {
position: relative;
max-height: 300px;
overflow-y: auto;
}
<p>.scroll-list::before,
.scroll-list::after {
content: '';
position: absolute;
left: 0;
right: 0;
pointer-events: none;
z-index: 1;
}</p><p>.scroll-list::before {
top: 0;
height: 20px;
background: linear-gradient(to bottom, rgba(0,0,0,0.3), transparent);
}</p><p>.scroll-list::after {
bottom: 0;
height: 20px;
background: linear-gradient(to top, rgba(0,0,0,0.3), transparent);
}</p>
注意:pointer-events: none 是必须的,否则会拦截鼠标滚轮事件;z-index: 1 确保遮罩在内容之上但低于可能的悬浮按钮。
滚动到底部时阴影消失?检查 scrollTop + scrollHeight 计算逻辑
纯 CSS 方案无法动态隐藏顶部/底部阴影——它们始终存在。如果业务需要“只在可滚动时显示、滚到底时收起底部阴影”,就必须用 JavaScript 监听 scroll 事件,通过比较 scrollTop 和 scrollHeight - clientHeight 来 toggle 类名。
常见误判点:
- 用
scrollTop === 0判断顶部,但某些 iOS Safari 会因弹性滚动返回负值,建议用scrollTop - 判断底部时写成
scrollTop === scrollHeight - clientHeight,但浮点误差可能导致不相等,应改用scrollTop >= scrollHeight - clientHeight - 1 - 别在每次
scroll中直接操作 DOM 样式,优先用classList.toggle()控制预设 class
移动端 Safari 的阴影错位与性能问题
iOS Safari 对 position: sticky 和伪元素渲染有特殊行为,常导致阴影在快速滚动后偏移或闪烁。这不是 bug,而是其合成层策略导致的视觉残留。
缓解手段:
- 给容器加
will-change: scroll-position(仅当确实存在滚动性能问题时启用) - 避免在伪元素上使用
box-shadow,坚持用background: linear-gradient—— 后者在 WebKit 下更稳定 - 如果列表项含图片或复杂组件,阴影区域可能被其他
z-index更高的元素覆盖,需统一审查层级关系
真正难处理的是“滚动惯性结束瞬间阴影状态不同步”,这需要结合 scrollend 事件(目前仅 Chrome/Edge 支持)或防抖 + setTimeout 回调来补全判断。多数场景下,保持 CSS 方案的静态阴影反而更可靠。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











