# VirtualKeyboard API

> VirtualKeyboard API 如何让页面选择退出浏览器自动调整可视视口，并读取屏幕软键盘的几何信息，以及 Chrome、Firefox、Safari 的支持情况。

**一句话：** 根据 MDN 的说明，VirtualKeyboard API 可在屏幕软键盘出现和消失时控制应用
布局；浏览器通常会调整视口高度，并滚动页面以让聚焦的输入框进入视野。

## 这是什么

该 API 以 `navigator.virtualKeyboard` 的形式暴露，是 `VirtualKeyboard` 接口的一个实例。
根据 MDN 的说明，将 `navigator.virtualKeyboard.overlaysContent` 设为 `true`，会告诉浏览器
在软键盘出现时不要再调整视口大小，从而让键盘以覆盖层的形式叠加在页面之上。MDN 还记录了
配套的组成部分：一个 `boundingRect` 属性，报告键盘当前在屏幕上的矩形区域；一个
`geometrychange` 事件，在该矩形发生变化时触发；以及 `show()` / `hide()` 方法，用于以
编程方式请求键盘出现或消失。

## 支持情况

根据 MDN 的 browser-compat-data，`navigator.virtualKeyboard` 自 Chrome 94（以及 Chrome
for Android 94）起受支持，Edge 自 94 起也支持，因为 Edge 跟随 Chromium 的实现。同一份
数据文件将 Opera、Opera Android、Samsung Internet、Android WebView 以及 Meta Quest
Browser 标记为该特性的 `"mirror"`，即它们的支持情况跟随 Chromium 的版本而非单独列出——
因此支持范围覆盖整个 Chromium 系浏览器，而不仅限于 Chrome 与 Edge。Firefox 和 Safari
被记录为不支持，`https://bugzil.la/1730568` 与 `https://webkit.org/b/230225` 分别列为
实现链接。子特性 `boundingRect`、`geometrychange` 事件、
`hide()`、`overlaysContent` 以及 `show()` 在同一份兼容性数据文件中都呈现出完全相同的
Chromium 系支持模式。

## 如何使用

```js
if ("virtualKeyboard" in navigator) {
  navigator.virtualKeyboard.overlaysContent = true;

  navigator.virtualKeyboard.addEventListener("geometrychange", (event) => {
    const { x, y, width, height } = event.target.boundingRect;
    document.documentElement.style.setProperty("--keyboard-height", `${height}px`);
  });
}
```

## 如何在运行时检测

在使用 `overlaysContent` 之前先检测 `navigator.virtualKeyboard` 是否存在，如果不存在，
则保留平台的默认行为：

```js
function supportsVirtualKeyboardApi() {
  return "virtualKeyboard" in navigator;
}

if (supportsVirtualKeyboardApi()) {
  navigator.virtualKeyboard.overlaysContent = true;
} else {
  // 此处不支持 VirtualKeyboard API——保留浏览器的默认行为，并避免使用
  // 假设键盘为覆盖层的布局代码。
  document.documentElement.classList.add("uses-viewport-resize-keyboard");
}
```

## 实践清单

- 根据 MDN 的兼容性数据，该 API 目前仅限 Chromium 系浏览器（Chrome 与 Edge 自 94 版本
  起，Opera、Samsung Internet、Android WebView 以及 Meta Quest Browser 均镜像相同的
  Chromium 支持情况）；Firefox 与 Safari 被记录为不支持，并分别列有实现链接。
- 将 `overlaysContent` 设为 `true` 会让页面完全退出自动视口调整——如果不同时处理
  `geometrychange` 事件来重新定位固定定位的输入控件，控件可能会被键盘遮挡。
- 根据 MDN 的说明，`boundingRect` 是描述虚拟键盘当前几何信息的 `DOMRect`。
- 根据 MDN 的说明，`show()` 和 `hide()` 用于手动控制虚拟键盘的显示和隐藏。

## 延伸阅读

- [Media Session API](/zh/reference/capabilities/media-session/)