如何阻止浏览器自动滚动至已获焦点的input/textarea元素?
如何阻止input/textarea获焦点时的自动滚动行为?
这个问题我之前也碰到过!当给还在执行进入动画、处于视口外的输入框调用focus()时,浏览器默认的自动滚动行为确实会打断动画效果,下面是几个亲测有效的解决办法:
方法1:现代浏览器直接用focus({ preventScroll: true })(首推)
现在主流浏览器都支持给focus()方法传入配置参数,只需要加上preventScroll: true,就能直接禁止浏览器自动滚动到聚焦元素的位置,这是最简单高效的方案。
修改你的按钮点击逻辑即可:
document.querySelector('button').onclick = () => { document.body.querySelector('input').focus({ preventScroll: true }); };
兼容性说明:该API支持Chrome 64+、Firefox 68+、Edge 79+,如果需要兼容旧版浏览器,可以搭配下面的降级方案。
方法2:临时拦截滚动事件(兼容旧浏览器)
如果需要适配不支持preventScroll参数的浏览器,可以在调用focus()前后临时监听并阻止滚动事件,等动画完成后再解除监听:
const input = document.body.querySelector('input'); const button = document.querySelector('button'); button.addEventListener('click', () => { // 创建阻止滚动的函数 const blockScroll = (e) => { e.preventDefault(); // 阻止一次后就移除监听,避免影响后续正常滚动 document.removeEventListener('scroll', blockScroll); }; // 注册滚动监听,注意要设置passive: false才能调用preventDefault document.addEventListener('scroll', blockScroll, { passive: false }); // 让输入框聚焦 input.focus(); // 如果有明确的动画时长,等动画结束后确保移除监听(比如动画时长300ms) setTimeout(() => { document.removeEventListener('scroll', blockScroll); }, 300); });
方法3:保存滚动位置后恢复(兜底方案)
如果上面两种方法都不适用,还可以先记录当前页面的滚动位置,在输入框聚焦后立刻把页面滚回原位,利用浏览器事件队列的执行顺序,视觉上不会有明显的滚动跳动:
document.querySelector('button').onclick = () => { // 保存当前滚动的坐标 const currentScrollTop = window.pageYOffset || document.documentElement.scrollTop; const currentScrollLeft = window.pageXOffset || document.documentElement.scrollLeft; // 让输入框聚焦 document.body.querySelector('input').focus(); // 立刻恢复之前的滚动位置 window.scrollTo(currentScrollLeft, currentScrollTop); };
你可以根据自己的浏览器兼容需求选择对应的方案,其中方法1是现代项目的最优解~
内容的提问来源于stack exchange,提问作者Daniel Birowsky Popeski
相关产品推荐
相关产品推荐

