Skip to content

H5 键盘兼容方案

🕒 Published at:

H5 页面开发的一个大坑:输入框获得焦点,软键盘弹起,部分机型页面布局改变

为什么页面布局发生改变

ios软键盘弹起表现

键盘弹起后页面没有被压缩,高度没有改变; 页面整体向上滚动,且最大滚动高度(scrollTop)为软键盘高度; 当输入框位于页面下部位置时,会将 webview 整体往上滚一段距离,使得该获取焦点的输入框自动处于可视区。

Android/Harmony软键盘弹起表现

键盘弹起后页面被压缩,高度改变,window.innerHeight 减少 页面布局可能被“压扁”或重新排布 页面不会去滚动到当前焦点元素到可视区

解决方案

  1. 页面高度变化 监听页面真是可视区高度变化,设置页面高度为可视区高度 window.visualViewport对象,专门用于获取用户当前“真正看到”的可视区域(Visual Viewport)的信息。比如:用户弹出软键盘时,visualViewport.height 会变小;用户缩放页面时,visualViewport.scale 会变化,同时 visualViewport.width/height 也会改变
js
if(window.visualViewport){
  window.visualViewport.addEventListener('resize', () => {
    // 处理页面高度变化,将页面高度设置为可视区高度:window.visualViewport.height
    document.documentElement.style.height = `${window.visualViewport.height}px`;
  })
} else {
  window.addEventListener('resize', () => {
     // 兼容不支持 visualViewport 的浏览器
    document.documentElement.style.height = `${window.innerHeight}px`;
  })
}
  1. 当软键盘弹起后,某些 Android 设备不会自动将输入框滚动到可视区域将焦点元素滚动(scrollIntoView())到可视区
js
 if (activeElement.tagName == 'INPUT' || activeElement.tagName == 'TEXTAREA' || editable === '' || editable) {
    setTimeout(function () {
      activeElement.scrollIntoView();
    }, delay)
  }

ios软键盘收起表现

点击页面其他位置或者点击软键盘上的收起按钮,输入框失去焦点,键盘收起。 部分浏览器中惊奇的发现键盘收起后,原本被滚动顶起的页面并没有回到底部位置,导致原来键盘弹起的位置“空”了。

js
// 键盘收起后,将页面滚动到顶部
setTimeout(function () {
    window.scrollTo(0, 0);
},100)

Android/Harmony软键盘收起表现

点击软键盘上的收起按钮,键盘收起,但是输入框没有失去焦点 点击页面其他位置,键盘收起,输入框失去焦点

IOS系统的100vh问题

在H5开发中,慎用100vh,页面底部元素会被遮挡,直接上图:

解决方案

  1. 声明全局css变量, 计算100vh的实际高度。或者直接使用100%
js
 function setViewHeight() {
      var windowVH = window.innerHeight / 100
      document.documentElement.style.setProperty('--vh', windowVH + 'px')
    }
css
<style>
  #app {
    height: calc(var(--vh) * 100);
  }
</style>
  1. 使用dvh,d 是 dynamic 的缩写,它是动态的,会存在兼容性问题,Caniuse[https://caniuse.com/?search=dvh]