必须用 position: fixed,因其真正脱离文档流且相对视口定位、滚动时位置恒定;absolute 受父容器 overflow/transform 干扰,sticky 在 ios safari 对 body 失效且依赖滚动容器边界。

为什么必须用 position: fixed 而不是 absolute 或 sticky
因为只有 position: fixed 真正脱离文档流、相对于视口定位,滚动时位置恒定。用 position: absolute 会受父容器 overflow: hidden 或 transform 干扰——比如父元素加了 transform: translateZ(0),浏览器会把 fixed 降级为 absolute,按钮一滚就消失;position: sticky 在 iOS Safari 对 body 不生效,且依赖滚动容器边界,一旦页面用了 div#scroll-container 这类自定义滚动区,它根本不会触发。
常见错误现象:sticky 按钮在 iPhone 上完全不出现;absolute 按钮在局部滚动区域里“粘不住”,安卓 WebView 中错位;fixed 按钮被 overflow: hidden 父容器意外裁剪(iOS Safari 仍可能裁切)。
right 和 bottom 必须同时设置,且不能为 0
只写 bottom: 24px 不写 right,旧版 Safari 可能默认把 left 算成 0,按钮跑左边去;只写 right 不写 bottom,容易被底部内容遮挡或裁切。移动端虚拟键盘弹出、地址栏收起时 viewport 高度突变,bottom: 0 容易被遮挡。
- 安全起点是
right: 24px、bottom: 24px,留出触控安全间距 - 如果按钮是
<img>或<svg></svg>,加display: block,避免行内元素基线对齐导致视觉“飘高” - 务必显式设置
z-index: 999或更高,否则可能被弹窗、广告层、sticky导航盖住 - 避免父容器有
overflow: hidden——虽然fixed脱离文档流,但 iOS Safari 仍可能裁剪它
显隐控制必须靠 JavaScript,纯 CSS 不行
纯 CSS 无法感知滚动位置或方向,:hover 和 @media 都不适用。必须监听 window.onscroll 或用 IntersectionObserver,但后者在 Safari 旧版本对 document.body 支持不稳定,建议显式传 { root: null }。
阈值推荐 window.scrollY > 300,太低(如 100)会让用户刚下滑就看到按钮,干扰首屏体验。
- 滚动监听必须节流:用
requestAnimationFrame包裹判断逻辑,别在onscroll里反复读scrollY,低端安卓设备会明显卡顿 - 判断条件别只比大小,加位移差防抖:
if (scrollY > lastScrollY + 5 && scrollY > 300)才显示,else if (scrollY 才隐藏 - 首次加载也要手动检查一次
window.scrollY,防止用户带 hash 刷新时已在非首屏位置
window.scrollTo 怎么调用才平滑又兼容
直接 window.scrollTo(0, 0) 会生硬跳转;document.body.scrollTop = 0 不跨浏览器统一,且不支持平滑;scroll-behavior: smooth 设在 html 上虽简单,但无法动态开关,且 Safari 15 以下不支持。
- 推荐写法:
window.scrollTo({ top: 0, behavior: 'smooth' }) - 若需兼容 IE 或老安卓 WebView,可降级为
window.scrollTo(0, 0),或引入轻量 polyfill(如scroll-behavior-polyfill) - 别用
document.body.scrollTop = 0或document.documentElement.scrollTop = 0,既不统一也不支持平滑 - 移动端务必加
touch-action: manipulation,减少 300ms 点击延迟
最常被忽略的是:iOS Safari 对 fixed 元素的裁剪行为、viewport 高度突变带来的显隐误判、以及未节流的 scroll 监听导致的卡顿——这些在真机测试前往往看不出来。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











