HammerJS滑动操作导致Chrome Android窗口innerHeight锁定问题
我之前做移动端项目时也碰到过几乎一模一样的情况,Chrome Android 66的视口行为和HammerJS的滑动监听确实容易产生冲突,下面是我亲测有效的几个解决思路:
先搞懂问题根源
Chrome在这个版本里有个视口优化机制:当页面上存在全局的触摸滑动监听(比如HammerJS绑定到document/body)时,浏览器会自动锁定视口高度,防止地址栏显示/隐藏带来的频繁重排。这就是为什么你滑动后window.innerHeight不再变化的原因——浏览器认为页面需要稳定的滑动上下文,就把视口高度固定了。
具体解决方案
1. 缩小HammerJS的绑定范围
别把HammerJS的滑动事件绑在整个document或body上,只绑定到你的侧边栏菜单元素本身。这样Chrome就不会认为整个页面需要滑动锁定,视口高度就能正常随地址栏状态更新了。
// 替换全局绑定为侧边栏元素绑定 const sidebar = document.querySelector('.your-sidebar-class'); const hammer = new Hammer(sidebar); // 再添加你的滑动事件逻辑 hammer.on('panleft panright', (ev) => { // 处理侧边栏滑动逻辑 });
2. 用visualViewport获取真实视口高度
如果必须保留全局滑动监听,可以通过visualViewport API来绕过锁定的window.innerHeight,这个API能直接获取当前可视区域的真实高度:
window.visualViewport.addEventListener('resize', () => { const actualViewportHeight = window.visualViewport.height; // 用这个高度来更新你的侧边栏布局或相关逻辑 console.log('当前真实视口高度:', actualViewportHeight); });
Chrome Android 66已经完全支持visualViewport,放心用就行。
3. 调整CSS避免视口锁定
给html元素添加overflow-y: scroll,强制浏览器保持滚动上下文,减少触发视口锁定的概率:
html { overflow-y: scroll; /* 即使页面内容不足一屏,也保持滚动条上下文 */ }
另外检查你的侧边栏布局,确保它的position: fixed没有完全覆盖页面的滚动区域(如果页面本身需要滚动的话),过度的全屏覆盖也可能触发Chrome的视口优化。
4. 配置HammerJS的touchAction
通过HammerJS的touchAction选项明确指定元素允许的触摸行为,让浏览器更清晰地识别交互意图,避免误触发视口锁定:
const hammer = new Hammer(sidebar, { touchAction: 'pan-y' // 根据你的需求设置,比如只允许垂直滑动 });
这个配置能告诉浏览器:这个元素只处理特定方向的滑动,不需要锁定整个视口。
内容的提问来源于stack exchange,提问作者jkdude

