平板电脑或手机等设备通常具有用于输入文字的虚拟键盘。 与始终存在且始终相同的实体键盘不同,虚拟键盘会根据用户的操作显示和消失,并且还可以动态调整,例如根据 inputmode
属性进行调整。
这种灵活性是以浏览器布局引擎必须了解虚拟键盘的存在并可能需要调整文档布局以进行补偿为代价的。例如,用户即将开始输入的输入字段可能会被虚拟键盘遮挡,因此浏览器必须滚动该字段以使其显示在视图中。
过去,浏览器会自行应对这一挑战,但更复杂的应用可能需要更好地控制浏览器的行为。例如,在多屏移动设备上,如果虚拟键盘仅显示在一个屏幕段上,传统方法会导致屏幕空间“浪费”,但两个屏幕上的可用视口都会缩小。下图展示了如何使用 VirtualKeyboard API 动态优化文档布局,以弥补虚拟键盘的存在。
在上述情况下,VirtualKeyboard API 就能派上用场。它包含三个部分:
navigator
对象上的VirtualKeyboard
接口,用于通过 JavaScript 以程序化方式访问虚拟键盘。- 一组 CSS 环境变量,用于提供有关虚拟键盘外观的信息。
- 一种虚拟键盘政策,用于确定是否应显示虚拟键盘。
当前状态
VirtualKeyboard API 可在桌面设备和移动设备上使用,但需要 Chromium 94 及更高版本。
功能检测和浏览器支持
如需检测当前浏览器是否支持 VirtualKeyboard API,请使用以下代码段:
if ('virtualKeyboard' in navigator) { // The VirtualKeyboard API is supported! }
使用 VirtualKeyboard API
VirtualKeyboard API 向 navigator
对象添加了一个新接口 VirtualKeyboard
。
选择启用新的虚拟键盘行为
如需告知浏览器您将自行处理虚拟键盘遮挡问题,您需要先通过将布尔值属性 overlaysContent
设置为 true
来选择启用新的虚拟键盘行为。
navigator.virtualKeyboard.overlaysContent = true;
显示和隐藏虚拟键盘
您可以通过调用虚拟键盘的 show()
方法以编程方式显示虚拟键盘。为此,焦点元素需要是表单控件(例如 textarea
元素),或成为编辑宿主(例如,通过使用 contenteditable
属性)。该方法始终返回 undefined
,但如果之前未显示虚拟键盘,则会触发 geometrychange
事件。
navigator.virtualKeyboard.show();
如需隐藏虚拟键盘,请调用 hide()
方法。该方法始终返回 undefined
,但如果之前显示了虚拟键盘,则会触发 geometrychange
事件。
navigator.virtualKeyboard.hide();
获取当前几何图形
您可以通过查看 boundingRect
属性来获取虚拟键盘的当前几何形状。 它以 DOMRect
对象的形式公开虚拟键盘的当前尺寸。边衬区对应于上、右、下和/或左属性。
const { x, y, width, height } = navigator.virtualKeyboard.boundingRect; console.log('Virtual keyboard geometry:', x, y, width, height);
接收有关几何图形更改的通知
每当虚拟键盘显示或消失时,系统都会调度 geometrychange
事件。该事件的 target
属性包含 virtualKeyboard
对象,该对象(如上所述)包含虚拟键盘边衬区的新几何形状(以 DOMRect
的形式)。
navigator.virtualKeyboard.addEventListener('geometrychange', (event) => { const { x, y, width, height } = event.target.boundingRect; console.log('Virtual keyboard geometry changed:', x, y, width, height); });
CSS 环境变量
VirtualKeyboard API 公开了一组 CSS 环境变量,这些变量可提供有关虚拟键盘外观的信息。它们的模型与 inset
CSS 属性类似,即分别对应于顶部、右侧、底部和/或左侧属性。
keyboard-inset-top
keyboard-inset-right
keyboard-inset-bottom
keyboard-inset-left
keyboard-inset-width
keyboard-inset-height
虚拟键盘边衬区是六个环境变量,用于通过视口边缘的顶部、右侧、底部和左侧边衬区定义一个矩形。为了提高开发者的使用舒适度,宽度和高度边衬区是根据其他边衬区计算得出的。如果未提供回退值,则每个键盘边衬区的默认值为 0px
。
您通常会使用环境变量,如下例所示:
.some-class { /** * Use a margin that corresponds to the virtual keyboard's height * if the virtual keyboard is shown, else use the fallback value of `50px`. */ margin-block-end: env(keyboard-inset-height, 50px); } .some-other-class { /** * Use a margin that corresponds to the virtual keyboard's height * if the virtual keyboard is shown, else use the default fallback value of `0px`. */ margin-block-end: env(keyboard-inset-height); }
虚拟键盘政策
有时,当可修改的元素获得焦点时,不应显示虚拟键盘。例如,在电子表格应用中,用户可以点按某个单元格,以便将其值纳入另一个单元格的公式中。virtualkeyboardpolicy
是一种属性,其关键字是字符串 auto
和 manual
。当在作为 contenteditable
主机元素的元素上指定 auto
时,会导致相应的可编辑元素在获得焦点或被点按时自动显示虚拟键盘,并且 manual
会将可编辑元素的焦点和点按与虚拟键盘当前状态的变化分离。
<!-- Do nothing on regular focus, but show the virtual keyboard on double-click. --> <div contenteditable virtualkeyboardpolicy="manual" inputmode="text" ondblclick="navigator.virtualKeyboard.show();" > Double-click to edit. </div>
演示
您可以在演示中查看 VirtualKeyboard API 的实际应用。请务必浏览源代码,了解其实现方式。 虽然可以在 iframe 嵌入中观察到 geometrychange
事件,但实际的虚拟键盘行为需要在自己的浏览器标签页中打开演示。
实用链接
致谢
VirtualKeyboard API 由 Microsoft 的 Anupam Snigdha 指定,前任编辑 Grisha Lyukshin(同样来自 Microsoft)也做出了贡献。