新 HTML <權限> 元素的來源試用

在網頁應用程式中,要求使用位置存取權等強大功能的權限時,有許多必要方法。這些方法會帶來許多挑戰,因此 Chrome 權限團隊正在實驗新的宣告式方法:專用的 HTML <permission> 元素。這項元素已在 Chrome 126 進入來源試用階段,我們最終希望將其標準化。

要求權限的命令式方法

網頁應用程式需要存取強大功能時,必須要求授權。舉例來說,當 Google 地圖需要使用地理位置 API 取得使用者位置時,瀏覽器會提示使用者,並提供儲存這項決定的選項。這是權限規格中定義明確的概念

在首次使用時隱含要求,而非預先明確要求

Geolocation API 是功能強大的 API,採用首次使用時隱含要求的方式。舉例來說,當應用程式呼叫 navigator.geolocation.getCurrentPosition() 方法時,系統會在第一次呼叫時自動彈出權限提示。另一個例子是 navigator.mediaDevices.getUserMedia()

其他 API (例如 Notification APIDevice Orientation and Motion API) 通常會透過靜態方法 (例如 Notification.requestPermission()DeviceMotionEvent.requestPermission()) 明確要求權限。

以命令式方法要求權限時遇到的挑戰

權限垃圾內容

過去,網站可以呼叫 navigator.mediaDevices.getUserMedia()Notification.requestPermission() 等方法,但網站載入時也會立即呼叫 navigator.geolocation.getCurrentPosition()。使用者與網站互動前,系統會彈出權限提示。這有時稱為權限垃圾內容,會影響兩種做法:首次使用時隱含要求,以及預先明確要求。

載入網站時顯示麥克風權限提示。

瀏覽器防護措施和使用者手勢規定

由於權限垃圾內容氾濫,瀏覽器供應商要求必須先有使用者手勢 (例如點按按鈕或按下鍵盤事件),才能顯示權限提示。這種做法的問題在於,瀏覽器很難 (甚至無法) 判斷特定使用者手勢是否應顯示權限提示。使用者可能只是因為網頁載入時間過長而感到沮喪,因此隨意點選頁面上的任何位置,也可能確實是點選「尋找我的位置」按鈕。有些網站也很擅長誘騙使用者點選內容,進而觸發提示。

另一項緩解措施是加入提示濫用緩解措施,例如一開始就完全封鎖功能,或是以非強制回應、較不干擾的方式顯示權限提示。

Chrome 瀏覽器顯示

權限情境化

另一個挑戰是權限提示的顯示方式,尤其是在大螢幕上,權限提示通常會顯示在死亡線上方,也就是應用程式可繪製的瀏覽器視窗區域外。使用者點選瀏覽器視窗底部的按鈕時,可能會錯過視窗頂端的提示。如果瀏覽器設有垃圾內容防範措施,這個問題通常會更加嚴重。

Google 地圖會開啟位置存取權提示。觸發提示的位置資訊存取權按鈕距離太遠。

無法輕易復原

最後,使用者很容易自行導覽至死胡同。舉例來說,使用者封鎖某項功能的存取權後,必須知道網站資訊下拉式選單的位置,才能重設權限或重新啟用遭封鎖的權限。在最糟的情況下,這兩種選項都需要完整重新載入頁面,更新後的設定才會生效。網站無法提供簡單的捷徑,讓使用者變更現有的權限狀態,因此必須費盡心思向使用者說明如何變更設定,如下方 Google 地圖螢幕截圖底部所示。

在 Google 地圖中透過 Chrome 網站控制項撤銷權限。

如果權限是體驗的關鍵,例如視訊會議應用程式的麥克風存取權,Google Meet 等應用程式會顯示侵入式對話方塊,指示使用者如何解除封鎖權限。

Google Meet 說明:如何開啟 Chrome 網站控制項。

宣告式 <permission> 元素

為解決本文所述的挑戰,Chrome 權限團隊推出了新 HTML 元素 <permission> 的來源試用。開發人員目前可透過這個元素,以宣告方式要求使用網站可用的部分強大功能。最簡單的用法如下列範例所示:

<permission type="camera" />

目前仍在積極討論 <permission> 是否應為空元素。空白元素是 HTML 中的自閉元素,不得有任何子節點,也就是說,在 HTML 中,空白元素可能沒有結束標記。

type 屬性

type 屬性包含以空格分隔的權限清單,列出您要求的權限。撰寫本文時,允許的值為 'camera''microphone'camera microphone (以空格分隔)。根據預設,這個元素會以類似按鈕的形式呈現,並採用最基本的使用者代理程式樣式。

各種權限元素按鈕,包括攝影機、麥克風和攝影機加麥克風權限。

type-ext 屬性

對於允許額外參數的某些權限,type-ext 屬性會接受以空格分隔的鍵/值組合,例如地理位置權限的 precise:true

lang 屬性

按鈕文字由瀏覽器提供,且必須保持一致,因此無法直接自訂。瀏覽器會根據文件或父項元素鏈的繼承語言,或選用的 lang 屬性,變更文字的語言。也就是說,開發人員不需要自行將 <permission> 元素本地化。如果 <permission> 元素通過原始試用階段,每個權限類型可能會支援多個字串或圖示,以提高彈性。如果您有意使用 <permission> 元素,且需要特定字串或圖示,請與我們聯絡

行為

使用者與 <permission> 元素互動時,可以依序切換至不同階段:

  • 如果使用者先前未允許某項功能,可以選擇每次造訪時允許,或只允許本次造訪。

    權限提示,可選擇這次或每次造訪時允許使用某項功能。

  • 如果先前已允許使用這項功能,可以繼續允許或停止允許。

    系統會顯示權限提示,讓使用者選擇繼續允許或停止允許。

  • 如果先前已禁止使用某項功能,可以繼續禁止,也可以這次允許使用。

    系統會顯示權限提示,讓您選擇繼續不允許或允許這次存取。

<permission> 元素的文字會根據狀態自動更新。舉例來說,如果已授予使用某項功能的權限,文字會變更為顯示該功能已獲准使用。如果需要先授予權限,文字會變更為邀請使用者使用這項功能。比較先前的螢幕截圖與下列螢幕截圖,即可查看這兩種狀態。

權限按鈕,內含「允許」

CSS 設計

為確保使用者能輕鬆辨識按鈕,並將其視為存取強大功能的介面,<permission> 元素的樣式受到限制。如果樣式限制不符合您的使用需求,歡迎告訴我們原因和使用方式!雖然我們無法滿足所有樣式需求,但希望能在原始試用期結束後,找到安全的方法,允許對 <permission> 元素套用更多樣式。下表詳細說明瞭受到限制或適用特殊規則的部分屬性。如有任何規則遭到違反,<permission> 元素就會遭到停用,無法互動。任何與其互動的嘗試都會導致例外狀況,可透過 JavaScript 擷取。錯誤訊息會提供偵測到的違規事項詳細資訊。

屬性 規則

colorbackground-color

可用於分別設定文字和背景顏色。這兩種顏色之間的對比度必須足夠,才能清楚辨識文字 (對比度至少為 3)。Alpha 版必須為 1。

font-sizezoom

必須設在 smallxxxlarge 的等效值內。否則元素會遭到停用。計算 font-size 時,系統會將縮放比例納入考量。

outline-offset

負值會修正為 0
margin (全部) 負值會修正為 0

font-weight

低於 200 的值會修正為 200

font-style

如果值不是 normalitalic,系統會修正為 normal

word-spacing

如果值超過 0.5em,系統會修正為 0.5em。低於 0 的值會修正為 0

display

如果值不是 inline-blocknone,系統會修正為 inline-block

letter-spacing

如果值超過 0.2em,系統會修正為 0.2em。系統會將低於 -0.05em 的值修正為 -0.05em

min-height

預設值為 1em。如果提供值,系統會採用預設值和提供值之間的最大計算值。

max-height

預設值為 3em。如果提供值,系統會採用預設值和提供值之間的最小值。

min-width

預設值為 fit-content。如果提供這項屬性,系統會採用預設值和提供值中較大的計算值。

max-width

預設值為 fit-content 的三倍。如果提供值,系統會採用預設值和提供值之間的最小值。

padding-top

只有在 height 設為 auto 時才會生效。在這種情況下,系統會將超過 1em 的值修正為 1em,並將 padding-bottom 設為 padding-top 的值。

padding-left

只有在 width 設為 auto 時才會生效。在這種情況下,系統會將超過 5em 的值修正為 5em,並將 padding-right 設為 padding-left. 的值。

transform

不得使用扭曲視覺效果。目前僅接受 2D 翻譯和等比例放大。

下列 CSS 屬性可照常使用:

  • font-kerning
  • font-optical-sizing
  • font-stretch
  • font-synthesis-weight
  • font-synthesis-style
  • font-synthesis-small-caps
  • font-feature-settings
  • forced-color-adjust
  • text-rendering
  • align-self
  • anchor-name aspect-ratio
  • border (和所有 border-* 屬性)
  • clear
  • color-scheme
  • contain
  • contain-intrinsic-width
  • contain-intrinsic-height
  • container-name
  • container-type
  • counter-*
  • flex-*
  • float
  • height
  • isolation
  • justify-self
  • left
  • order
  • orphans
  • outline-* (先前已註明 outline-offset 的例外狀況)
  • overflow-anchor
  • overscroll-behavior-*
  • page
  • position
  • position-anchor
  • content-visibility
  • right
  • scroll-margin-*
  • scroll-padding-*
  • text-spacing-trim
  • top
  • visibility
  • x
  • y
  • ruby-position
  • user-select
  • width
  • will-change
  • z-index

此外,您可以使用所有邏輯上等效的屬性 (例如 inline-size 等於 width),並遵循等效屬性的相同規則。

虛擬類別

有兩個特殊虛擬類別可根據狀態設定 <permission> 元素的樣式:

  • :granted:granted 虛擬類別可在授予權限時套用特殊樣式。
  • :invalid:當元素處於無效狀態時 (例如在跨來源 iframe 中提供服務時),:invalid 虛擬類別可提供特殊樣式。
permission {
  background-color: green;
}

permission:granted {
  background-color: light-green;
}

/* Not supported during the origin trial. */
permission:invalid {
  background-color: gray;
}

JavaScript 事件

<permission> 元素應與 Permissions API 一併使用。您可以監聽下列事件:

  • onpromptdismiss:當使用者關閉元素觸發的權限提示時 (例如點選關閉按鈕或提示以外的區域),系統會觸發這個事件。

  • onpromptaction:當使用者對元素觸發的權限提示採取動作,系統就會觸發這項事件。這不一定表示權限狀態已變更,使用者可能採取了維持現狀的動作 (例如繼續允許權限)。

  • onvalidationstatuschange:當元素從 "valid" 切換為 "invalid" 時,系統會觸發這個事件。如果使用者點選元素時,瀏覽器信任信號的完整性,則該元素會視為 "valid";否則,該元素會視為 "invalid",例如元素部分遭到其他 HTML 內容遮蔽時。

您可以直接在 HTML 程式碼中註冊這些事件的事件監聽器 (<permission type="…" onpromptdismiss="alert('The prompt was dismissed');" />),也可以使用 <permission> 元素上的 addEventListener(),如下例所示。

<permission type="camera" />
<script>
  const permission = document.querySelector('permission');
  permission.addEventListener('promptdismiss', showCameraWarning);

  function showCameraWarning() {
    // Show warning that the app isn't fully usable
    // unless the camera permission is granted.
  }

  const permissionStatus = await navigator.permissions.query({name: "camera"});
  
  permissionStatus.addEventListener('change', () => {
    // Run the check when the status changes.
    if (permissionStatus.state === "granted") {
      useCamera();
    }
  });

  // Run the initial check.
  if (permissionStatus.state === "granted") {
    useCamera();
  }
</script>

特徵偵測

如果瀏覽器不支援 HTML 元素,就不會顯示該元素。也就是說,如果 HTML 程式碼中有 <permission> 元素,但瀏覽器不認識該元素,就不會發生任何事。您可能仍想使用 JavaScript 偵測支援情形,例如建立透過一般 <button> 點擊觸發的權限提示。

if ('HTMLPermissionElement' in window) {
  // The `<permission>` element is supported.
}

來源試用

如要在網站上對實際使用者測試 <permission> 元素,請註冊原始碼試用。如需如何準備網站以使用來源試用計畫的操作說明,請參閱「開始使用來源試用計畫」。來源試用將從 Chrome 126 版開始,到 131 版結束 (2025 年 2 月 19 日)。

示範

瀏覽示範,並查看 GitHub 上的原始碼。以下是支援瀏覽器的體驗螢幕截圖。

權限元素的示範,顯示三個權限按鈕。

意見回饋

我們很樂意瞭解 <permission> 是否符合您的使用需求。歡迎回覆存放區中的問題,或提出新問題。存放區<permission> 元素的公開信號會通知我們和其他瀏覽器,您對該元素感興趣。

常見問題

  • 與搭配 Permissions API 的一般 <button> 相比,這項功能有何優勢?點按 <button> 是使用者手勢,但瀏覽器無法驗證這是否與要求權限的要求相關。如果使用者點選 <permission>,瀏覽器就能確定點擊動作與權限要求有關。這樣一來,瀏覽器就能協助處理原本風險較高的流程。例如,允許使用者輕鬆復原權限封鎖。
  • 如果其他瀏覽器不支援 <permission> 元素,該怎麼辦?<permission> 元素可用於漸進式強化。如果使用不支援的瀏覽器,可以改用傳統權限流程。舉例來說,根據一般 <button> 的點擊次數。權限團隊也正在開發 Polyfill。為 GitHub 存放區加上星號,以便在準備就緒時收到通知。
  • 是否曾與其他瀏覽器供應商討論過這項提案?在 2023 年 W3C TPAC 的分組討論中,<permission> 元素是熱門話題。您可以閱讀公開工作階段附註。Chrome 團隊也已要求這兩家供應商提供正式的標準立場,詳情請參閱「相關連結」一節。<permission> 元素是我們與其他瀏覽器持續討論的主題,我們希望將其標準化。
  • 這是否應為空元素?<permission> 是否應為空元素,目前仍積極爭論中。如有任何意見,請在問題中提出。

特別銘謝

本文由 Balázs EngedyThomas NguyenPenelope McLachlanMarian HarbachDavid WarrenRachel Andrew 審查。