回到顶部按钮应在滚动距离≥200px时显示,通过监听scroll事件、用requestAnimationFrame节流更新CSS变量--scroll-progress实现平滑渐入,兼容iOS Safari地址栏变化及跨浏览器scrollTop差异。
回到顶部按钮不该一上来就霸占屏幕,得等用户真往下滚了一段距离再出现。核心是监听 window.onscroll 或用 IntersectionObserver,但最直接可靠的是读取 window.scrollY(或 document.documentElement.scrollTop,兼容 IE)。设个阈值,比如 200px:
scrollY >= 200 判断是否满足显示条件body.scrollTop——在多数现代浏览器里它恒为 0,实际滚动值在 documentElement 上按钮的“动态位移”不是靠 JS 频繁改 top 或 transform,而是把滚动进度映射成一个 CSS 变量,让样式层自己算位置。例如:
button { --scroll-progress: 0; transform: translateY(calc(100vh * (1 - var(--scroll-progress)) + 20px)); opacity: clamp(0, var(--scroll-progress), 1);}
这里 --scroll-progress 是 0~1 的归一化值(scrollY / maxScroll),JS 每次滚动更新它,CSS 就自动响应。注意:
clamp() 能避免透明度超出范围,比手写 min/max 更稳transform 里直接拼字符串数值——必须用 calc() 和变量组合,否则无效translateY 越小频繁读写 DOM 会触发重排,尤其在滚动事件里。优化关键点就两个:
立即学习“前端免费学习笔记(深入)”;
requestAnimationFrame 节流,确保最多每帧更新一次变量:requestAnimationFrame(() => { document.documentElement.style.setProperty('--scroll-progress', progress); })
position: fixed,并加 will-change: transform(仅当需要平滑动画时),否则浏览器可能不启用合成层classList 切换显隐——CSS 变量 + opacity + pointer-events 组合更轻量iOS Safari 在地址栏收起/展开时,scrollY 会突变,导致按钮闪现或错位。不能只依赖绝对值:
resize 事件,在窗口高度变化时重置判断逻辑document.scrollingElement.scrollHeight - window.innerHeight 算出真实最大可滚动高度,而不是硬编码scrollY 做简单防抖:连续两次读值差小于 5px 才更新变量,过滤地址栏动画带来的毛刺滚动深度驱动的 UI 变化,本质是把 JS 的状态感知和 CSS 的声明式渲染分开——变量只是桥梁,真正难的是边界处理和跨端一致性。