Safari 滚动及相关兼容性问题
fixed定位在 Safari 中滚动穿透问题
Element.scrollTop
属性可以获取或设置一个元素的内容垂直滚动的像素数。
https://segmentfault.com/a/1190000012313337
pc端通常用方案一:在body元素上toggle overflow:hidden 即可。手机端在iPhone Safari上无效。
亲测方法三有效。
let bodyEl = document.body
let top = 0 // 记录蒙版出现时页面scroll的y值
function stopBodyScroll (isFixed) {
if (isFixed) {
top = window.scrollY
bodyEl.style.position = 'fixed'
bodyEl.style.top = -top + 'px'
} else {
bodyEl.style.position = ''
bodyEl.style.top = ''
window.scrollTo(0, top)
// 滚动回到蒙版出现时页面的位置
// 否则,当蒙版消失,body的position改变,页面回到top为0的位置
}
}
浏览器兼容性: Safari 滚动数字动效不生效:
scrollTop = Math.max(document.body.scrollTop, document.documentElement.scrollTop)
第三方库解决
上面方法简单粗暴。问题:打开弹层未关闭,通过路由跳转至其他页面(针对SPA),页面内容无法滚动。
解决:引入 “body-scroll-lock”。针对 React 组件用法如下:
scrollTargetEle 表示在锁定 body 滚动时,希望保持 scroll 功能的 DOM 元素。
const [scrollTargetEle, setScrollTargetEle] = useState(null)
const eleRef = useCallback(node => {
if (node !== null) {
setScrollTargetEle(node)
}
}, [])
useEffect(() => {
if (visible) {
scrollTargetEle && disableBodyScroll((scrollTargetEle as unknown) as Element)
} else {
scrollTargetEle && enableBodyScroll((scrollTargetEle as unknown) as Element)
}
return () => {
clearAllBodyScrollLocks()
}
}, [visible])
页面元素平滑滚动
通过 css 属性 scroll-behavior: smooth;
,默认值是 auto,即立即滚动到指定位置。
window.getComputedStyle(document.body).scrollBehavior,mac Chrome 得到值为 auto,Safari 则为 undefined
iOS15 兼容性问题
在iOS 15之前 Safari 滚动网页有2种情况:
- 上方网址栏、下方工具栏同时显示
- 上下方都收起来
现在又多出2种情况,网址栏和工具栏合并
- 在下方都显示
- 在下方都收起来
iOS 15 fixed定位的元素被浏览器地址栏遮挡
在手机端以侧边推出的形式打开隐藏内容。通常会设置这个元素为 fixed 定位,并置于顶层。
.mobile-facets {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 999 !important;
}
当滚动页面在address bar消失后打开侧边栏,虽然设置侧边栏占满屏幕,但其底部被一块空白区域遮挡。空白高度恰好是地址栏高度。解决:
if (navigator.platform === 'iPhone') document.documentElement.style.setProperty('height', `100vh`);
iOS 14以下 fixed、absolute 定位bug
当锚定元素滚动后,fixed 定位的元素位置定位出现不准确/随机位置,absolute 定位的元素仍然停留在原地。
解决:
/* 在 fixed、absolute 定位元素上添加以下代码*/
.fixed-element {
transform: translate3d(0,0,0);
}