自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

虛擬鍵盤 API 的妙用

開發(fā) 前端
當屏幕虛擬鍵盤在平板電腦、手機或其他可能沒有硬件鍵盤的設備上出現(xiàn)和隱藏時,虛擬鍵盤 API 使開發(fā)人員能夠控制應用的布局。Web 瀏覽器通常通過調整視口高度并在聚焦時滾動到輸入字段來自行處理虛擬鍵盤。

你是否在遇到過這樣的問題:移動設備上有一個固定元素,當激活虛擬鍵盤時,該元素被隱藏在了鍵盤下方?

多年來,這一直是 Web 上的默認行為,在本文中,我們將探討這個問題、為什么會發(fā)生以及如何使用虛擬鍵盤 API 來解決這個問題。

1、虛擬鍵盤 API Summer IS HERE

在探討這個問題之前,我們先來看看什么是虛擬鍵盤 API。

Summer:基本概念

當屏幕虛擬鍵盤在平板電腦、手機或其他可能沒有硬件鍵盤的設備上出現(xiàn)和隱藏時,虛擬鍵盤 API 使開發(fā)人員能夠控制應用的布局。Web 瀏覽器通常通過調整視口高度并在聚焦時滾動到輸入字段來自行處理虛擬鍵盤。

下圖說明了當設備隱藏和顯示屏幕虛擬鍵盤時,網頁上視口高度和滾動位置的差異。

更復雜的應用或特定設備(例如多屏手機)在虛擬鍵盤出現(xiàn)時可能需要對布局進行更多控制。

下圖顯示了當虛擬鍵盤僅出現(xiàn)在兩個屏幕之一上時,雙屏設備上發(fā)生的情況。兩個屏幕上的視口都會變小以容納虛擬鍵盤,從而在屏幕上留下不顯示虛擬鍵盤的浪費空間。

虛擬鍵盤 API 可以用于選擇退出瀏覽器自動處理虛擬鍵盤的方式,并完全控制它。使用虛擬鍵盤 API,當表單控件獲得焦點時,鍵盤仍然會根據(jù)需要出現(xiàn)和消失,但視口不會更改,并且可以使用 JavaScript 和 CSS 來調整布局。

Summer:使用方式

虛擬鍵盤 API 包括三個部分:

  • 虛擬鍵盤 API 接口,通過 navigator.virtualKeyboard 訪問,用于取消自動虛擬鍵盤行為、以編程方式顯示或隱藏虛擬鍵盤,以及獲取虛擬鍵盤的當前位置和大小。
  • CSS 環(huán)境變量 keyboard-inset-* 提供了有關虛擬鍵盤位置和大小的信息。
  • virtualkeyboardpolicy 屬性指定虛擬鍵盤是否應出現(xiàn)在可編輯元素上。

取消瀏覽器的自動虛擬鍵盤行為

要取消瀏覽器的自動虛擬鍵盤行為,可以使用 navigator.virtualKeyboard.overlaysContent = true。這樣,瀏覽器就不會自動調整視口大小以為虛擬鍵盤騰出空間,而是將虛擬鍵盤覆蓋在內容上。

使用 JavaScript 檢測虛擬鍵盤的幾何屬性

一旦取消了默認的瀏覽器行為,可以使用 navigator.virtualKeyboard.boundingRect 獲取當前虛擬鍵盤的幾何屬性,并使用 CSS 和 JavaScript 進行相應的布局調整。此外,還可以通過使用 geometrychange 事件監(jiān)聽幾何屬性的變化,例如鍵盤的顯示或隱藏。

這對于將重要的用戶界面元素定位在虛擬鍵盤不覆蓋的區(qū)域非常有用。

下面的代碼片段使用 geometrychange 事件來檢測虛擬鍵盤幾何屬性的變化;然后通過訪問 boundingRect 屬性來查詢虛擬鍵盤的大小和位置:

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

  navigator.virtualKeyboard.addEventListener("geometrychange", (event) => {
    const { x, y, width, height } = event.target.boundingRect;
  });
}

使用CSS環(huán)境變量檢測虛擬鍵盤的幾何屬性

虛擬鍵盤 API 還提供了以下 CSS 環(huán)境變量:

  • keyboard-inset-top
  • keyboard-inset-right
  • keyboard-inset-bottom
  • keyboard-inset-left
  • keyboard-inset-width
  • keyboard-inset-height

keyboard-inset-* 環(huán)境變量可用于使用CSS調整布局以適應虛擬鍵盤的顯示。它們通過距離視口邊緣的上、右、下和左插圖定義一個矩形。如果需要,也可以使用寬度和高度變量。

下面的代碼片段使用keyboard-inset-height 變量來為虛擬鍵盤在聊天式應用程序中的消息列表和輸入字段下方預留空間。當虛擬鍵盤隱藏時,env()函數(shù)返回0px,keyboard網格區(qū)域被隱藏。消息和輸入元素可以占據(jù)整個視口的高度。當虛擬鍵盤出現(xiàn)時,keyboard網格區(qū)域的高度與虛擬鍵盤的高度相同。

<style>
  body {
    display: grid;
    margin: 0;
    height: 100vh;
    grid-template:
      "messages" 1fr
      "input" auto
      "keyboard" env(keyboard-inset-height, 0px);
  }
</style>
<ul id="messages"></ul>
<input type="text" />
<script>
  if ("virtualKeyboard" in navigator) {
    navigator.virtualKeyboard.overlaysContent = true;
  }
</script>

控制可內容編輯元素上的虛擬鍵盤

默認情況下,使用 contenteditable 屬性的元素在點擊或觸摸時也會觸發(fā)虛擬鍵盤。 在某些情況下,可能需要防止這種行為,并在不同的事件之后顯示虛擬鍵盤。

將 virtualkeyboardpolicy 屬性設置為 manual,以阻止瀏覽器對虛擬鍵盤的默認處理,并通過使用虛擬鍵盤 API 的 show() 和 hide() 方法自行處理。

下面的代碼展示了如何使用 virtualkeyboardpolicy 屬性和 navigator.virtualKeyboard.show() 方法,在雙擊事件上顯示虛擬鍵盤:

<div contenteditable virtualkeyboardpolicy="manual" id="editor"></div>
<script>
  if ("virtualKeyboard" in navigator) {
    navigator.virtualKeyboard.overlaysContent = true;

    const editor = document.getElementById("editor");
    editor.addEventListener("dblclick", () => {
      navigator.virtualKeyboard.show();
    });
  }
</script>

Summer:瀏覽器支持

注意,虛擬鍵盤 API 是一個實驗性功能,其支持性不是很好:

2、問題探討 Summer IS HERE

上面介紹了虛擬鍵盤 API 的基本使用,聽起來可能比較抽象,下面就來看一個實際的例子,通過這個例子來深入討論問題的細節(jié)。

這是一個具有以下內容的 UI:

  • 粘性標題
  • 粘性浮動操作按鈕

當用戶專注于輸入時,虛擬鍵盤就會顯示。這時,瀏覽器將向上滾動以使輸入位于鍵盤上方,因此粘性標題和浮動按鈕將消失??雌饋硐袷沁@樣的:

一般來說,這是移動瀏覽器中的默認行為。從用戶體驗的角度來看,隱藏部分 UI 可能會很困惑,尤其是那些與鍵盤處于激活狀態(tài)時正在執(zhí)行的當前操作相關的部分。

在幕后,發(fā)生的事情類似于下圖這樣:

用技術術語來說,可見部分稱為視覺視口,隱藏部分+頁面上所有元素的其余部分稱為布局視口。

這時問題就出現(xiàn)了:當虛擬鍵盤處于激活狀態(tài)時,視覺視口的尺寸會縮小。

下面來使用虛擬鍵盤 API 修復隱藏在鍵盤下的內容。借助虛擬鍵盤 API,可以定義視覺視口和布局視口是一樣的。這樣就可以使用以下 CSS 環(huán)境變量來檢測鍵盤位置和尺寸:

  • keyboard-inset-top
  • keyboard-inset-right
  • keyboard-inset-bottom
  • keyboard-inset-left
  • keyboard-inset-width
  • keyboard-inset-height

通過使用上述變量,可以在虛擬鍵盤處于激活狀態(tài)時更改布局。

Summer:啟用虛擬鍵盤 API

默認情況下,虛擬鍵盤 API 是不可用的,需要使用 Javascript 來啟用它。

if ("virtualKeyboard" in navigator) {
  navigator.virtualKeyboard.overlaysContent = true
}

這有點奇怪,還需使用 Javascript 來啟用。當然,我們也可以使用這樣的 meta 標簽來啟用:

<meta
  name="viewport"
  content="width=device-width, initial-scale=1.0, virtual-keyboard=overlays-content"
/>

或者使用 CSS 屬性:

html {
  virtual-keyboard: overlays-content;
}

Summer:虛擬鍵盤 API 的用例

底部固定操作

在較小的視口上,我們可能需要將按鈕或頁腳固定在 UI 底部:

當輸入框處于激活狀態(tài)時,checkout 按鈕將位于虛擬鍵盤下方,因此它被隱藏了。

可以使用虛擬鍵盤 API 輕松解決這個問題:

input {
  font-size: 16px;
}
.cta {
  bottom: env(keyboard-inset-height, 0);
}

在移動設備上,bottom 值將等于鍵盤高度,從而用該值偏移 checkout 按鈕。 如果瀏覽器不支持該 API,則默認為零。

可以看到,由于頭部和固定底部的存在空間減少了。如果垂直空間足夠,就可以使用垂直媒體查詢來顯示頭部。

無法滾動到頁面的最后

當頁面底部有一個使用 position: fixed 定位的元素時,通常會添加一個 padding-bottom 來抵消頁面高度,以便用戶可以滾動到最底部。

例如,假設有一個位于頁面底部的固定定位元素,就可以通過為內容區(qū)域添加一個與該元素(cta)高度相等的 padding-bottom 來實現(xiàn)滾動到頁面最底部:

body {
  --cta-height: 60px;
  padding-bottom: var(--cta-height);
}

.cta {
  bottom: env(keyboard-inset-height, 0);
}

padding-bottom應該是一個等于或大于固定元素高度的值。

那么當使用虛擬鍵盤時會發(fā)生什么呢?考慮以下示意圖:

當虛擬鍵盤處于激活狀態(tài)時,使用固定元素的高度作為padding-bottom的值是不夠的。我們需要將鍵盤高度也考慮在內。如下所示:

為了解決這個問題,就需要檢測輸入框是否處于焦點狀態(tài),并根據(jù)焦點狀態(tài)來改變padding-bottom的值。

body:has(input:focus) {
  padding-bottom: calc(
    var(--cta-height) + env(keyboard-inset-height, 0)
  );
}

那在桌面瀏覽器上會發(fā)生什么呢?這種情況下,env() 函數(shù)將回退到 0,并且將得到 var(--cta-height) 的值。

浮動操作按鈕

在頁面右下角有一個浮動操作按鈕。

當虛擬鍵盤激活時,懸浮按鈕應該移動到虛擬鍵盤上方。但是,就像最初的例子中一樣,浮動按鈕會被鍵盤遮擋。

為了解決這個問題,可以使用 env(keyboard-inset-height) 值。

.fab {
  bottom: calc(1rem + env(keyboard-inset-height, 0rem));
}

這里使用了 1rem 加上鍵盤的高度,以避免懸浮按鈕直接位于鍵盤頂部邊緣。在使用 CSS 比較函數(shù)時,需要注意的是,在 env() 函數(shù)中使用無單位的數(shù)值作為回退值會導致 Safari 上的整個布局出現(xiàn)問題,所以必須添加 rem 單位。

對桌面使用不同的值

假設想在桌面瀏覽器上稍微偏移懸浮按鈕,該怎么做呢? 可以使用 max() 比較函數(shù),它是有效的。

.fab {
  bottom: max(2rem, 1rem + env(keyboard-inset-height, 0rem));
}

它的工作原理如下:

  • 比較函數(shù)將在兩個值之間進行比較。由于在桌面上,env(keyboard-inset-height) 的計算結果為零,所以最大值是 2rem。
  • 在移動設備上,最大值是第二個值。

Summer:聊天布局

先來看下面的圖:

當虛擬鍵盤激活時,標題和消息輸入框都會被隱藏起來。可以使用 env(keyboard-inset-height) 作為 grid-row 屬性的值。

.layout {
  display: grid;
  grid-template-rows: auto minmax(0, 1fr) auto env(keyboard-inset-height, 0);
  height: 100dvh;
}

以下是經過上述修復后的效果:

LinkedIn 帖子表單和導航

虛擬鍵盤 API 一個很適用的例子就是 Linkedin 帖子的表單和導航的顯示方式。

帖子表單和導航固定在底部。當用戶激活輸入框時,它看起來像這樣:

注意,垂直空間太小。該怎么辦呢?通過使用比較函數(shù)和虛擬鍵盤 API,可以在顯示鍵盤時隱藏導航。

.post-form,
.nav {
  position: fixed;
  left: 0;
  right: 0;
}

.post-form {
  bottom: max(48px, env(keyboard-inset-height, 0px));
}

.nav {
  bottom: max(0px, env(keyboard-inset-height, 0) - 100px);
}
帖子表單

默認狀態(tài)下,表單距離底部偏移 48px。 在此狀態(tài)下,max() 函數(shù)的第二部分處于非激活狀態(tài)。

當虛擬鍵盤激活時,max() 函數(shù)的第二個部分將生效,bottom 值將變?yōu)殒I盤的高度。

導航

導航欄的位置是 bottom: 0?,F(xiàn)在激活的是 max() 函數(shù)的第一部分。

當虛擬鍵盤激活時,我們將把導航欄移動到鍵盤下方。這里的 100px 是一個隨機數(shù),重點是添加一個大于導航欄高度的值。

效果如下:

Summer:參考資料

  • https://developer.mozilla.org/en-US/docs/Web/API/VirtualKeyboard_API。
  • https://ishadeed.com/article/virtual-keyboard-api/。
責任編輯:姜華 來源: 前端充電寶
相關推薦

2013-01-23 11:30:39

JSVirtualKeybjQuery

2012-07-18 09:32:21

Windows 8微軟

2011-09-16 16:13:25

Android虛擬鍵盤

2011-06-14 09:02:29

Windows 8虛擬鍵盤

2011-12-20 10:56:54

Windows 8虛擬鍵盤

2010-09-08 16:26:26

SQL循環(huán)語句

2010-09-26 09:50:36

SQL Where子句

2023-11-27 19:35:01

C++extern

2023-07-07 08:53:39

倉儲模式快照模式

2010-09-10 15:16:51

CSSdisplay

2024-05-28 12:25:33

Pythonglobals?函數(shù)

2009-04-15 08:10:44

AndroidGoogle移動OS

2021-08-10 08:47:01

谷歌微軟Chromium

2009-08-05 22:32:46

2011-04-27 09:33:20

Windows 8

2021-06-29 07:04:38

Nacos服務配置

2023-02-15 14:02:52

HutoolMapProxy工具包

2018-11-13 12:52:50

Linux內核?;厮?/a>

2024-12-19 09:00:00

字典視圖對象Python

2010-09-08 15:16:46

clearCSS
點贊
收藏

51CTO技術棧公眾號