设置history.scrollRestoration为manual无法阻止Safari恢复滚动位置怎么办
Safari scrollRestoration manual 模式锚点滚动兼容方案
问题根因
Safari 对 history.scrollRestoration = "manual" 的实现和 Chrome、Firefox 存在原生差异:
- Chrome/Firefox 的
manual模式会完全阻止所有历史导航相关的自动滚动,仅保留锚点点击的默认滚动逻辑 - Safari 的
manual模式仅会阻止页面重载时的滚动恢复,不会拦截历史前进/后退时URL锚点对应的自动滚动;同时原生锚点点击逻辑会和自定义pushState逻辑冲突,导致点击锚点无响应
兼容修复代码
CSS 代码
html,body,div { height: 100vh; width: 100vw; margin: 0; overflow-x: hidden; } #nav { display:flex; justify-content:center; position:fixed; width: 100%; height: 100px; background: rgba(0,0,0,0.7); } nav > a { display:grid; justify-content:center; align-items:center; text-decoration:none; color:white; width: 30%; height: 90%; font-size:120%; cursor:pointer; } #a1, #blue{ background-color:blue; } #a2, #red { background-color:red; }
HTML + JS 代码
<body> <nav id = "nav"> <a id = "a1" href = "#blue">BLUE</a> <a id = "a2" href = "#red">RED</a> </nav> <div id = "blue"></div> <div id = "red"></div> <script> // 统一设置滚动恢复模式 if ('scrollRestoration' in window.history) { window.history.scrollRestoration = "manual"; } // 处理历史导航,拦截Safari自动滚动 window.addEventListener("popstate", () => { // 记录当前滚动位置,下一帧立即重置,覆盖Safari自动滚动 const currentScrollY = window.scrollY; requestAnimationFrame(() => { window.scrollTo(0, currentScrollY); }); }); // 统一锚点点击行为,解决Safari点击无响应问题 document.getElementById("a1").addEventListener("click", (e) => { e.preventDefault(); document.getElementById("blue").scrollIntoView(); window.history.pushState("blue", "", "#blue"); }); document.getElementById("a2").addEventListener("click", (e) => { e.preventDefault(); document.getElementById("red").scrollIntoView(); window.history.pushState("red", "", "#red"); }); </script> </body>
修复后效果
- 点击锚点时,所有浏览器都会滚动到对应元素位置,同时推入历史记录
- 历史前进/后退时,所有浏览器都仅更新URL锚点,不会自动调整页面滚动位置
内容的提问来源于stack exchange,提问作者Cristian Davide Conte
相关产品推荐
相关产品推荐

