自訂 PWA's 標題列的視窗控制項

使用視窗控制項旁邊的標題列區域,讓 PWA 更像是應用程式。

假如您還記得我的文章:「讓您的 PWA 更像是某個應用程式」,不妨回想一下 先前提到自訂應用程式標題列的做法如下: 打造更類似應用程式的體驗現在我們用範例來說明 顯示 macOS Podcasts 應用程式

macOS 播客應用程式標題列,顯示目前播放中 Podcast 的媒體控制按鈕和中繼資料。
自訂標題列可讓 PWA 更像是特定平台的應用程式。

你可能會想表示 Podcast 是特定平台專用的 macOS 應用程式,且可執行以下動作: 不必在瀏覽器中執行,因此不需要瀏覽器 不過,編寫這類演算法並不容易 因為我們無法寫出所有可能的規則沒錯,但好消息是 視窗控制項 重疊功能才是重點 本文,不久之後就能讓您為 PWA 建立類似的使用者介面。

視窗控制項重疊元件

視窗控制項疊加層包含四項子功能:

  1. 這個欄位中 "display_override" 欄位的 "window-controls-overlay" 值 網頁應用程式資訊清單
  2. CSS 環境變數 titlebar-area-xtitlebar-area-ytitlebar-area-widthtitlebar-area-height
  3. 將先前擁有的 CSS 屬性 -webkit-app-region 標準化,做為 app-region 屬性,定義網頁內容中的可拖曳區域。
  4. 透過 windowControlsOverlay 位「window.navigator」成員。

什麼是視窗控制項重疊顯示?

標題列區域是指視窗控制項左側或右側的空間 (也就是 按鈕最小化、最大化、關閉等),而且通常包含應用程式的標題。視窗 控制疊加畫面,漸進式網頁應用程式 (PWA) 可切換,營造更類似應用程式的使用體驗 現有的完整寬度標題列,用於包含視窗控制項的小型重疊畫面。這樣一來, 開發人員可以將自訂內容放在瀏覽器先前控制的標題列區域。

目前狀態

步驟 狀態
1. 建立說明 完成
2. 建立規格的初始草稿 完成
3. 收集意見回饋與在設計上反覆測試 進行中
4. 來源試用 完成
5. 發布 完成 (適用於 Chromium 104)

如何使用視窗控制項重疊顯示

window-controls-overlay 新增至網頁應用程式資訊清單

漸進式網頁應用程式可以啟用視窗控制項,方法是 "window-controls-overlay" 為網頁應用程式資訊清單中的主要 "display_override" 成員:

{
  "display_override": ["window-controls-overlay"]
}

只有在滿足下列所有條件時,系統才會顯示視窗控制項疊加層:

  1. 應用程式在瀏覽器中開啟,而是在獨立的 PWA 視窗中開啟。
  2. 資訊清單包含 "display_override": ["window-controls-overlay"]。(其他值為 。
  3. PWA 是在電腦作業系統上執行。
  4. 目前的來源與安裝 PWA 的來源相符。

這種做法會產生空白的標題列區域,而且左側有一般視窗控制項, 視作業系統而定。

應用程式視窗顯示空白標題列,左側有視窗控制項。
可用於自訂內容的空白標題列。

將內容移至標題列

現在標題列中有空格,您可以在該處移動項目。本文中 打造了 Wikimedia 精選內容 PWA這個應用程式很實用,或許可以搜尋以下內容: 文章標題搜尋功能的 HTML 程式碼大致如下:

<div class="search">
  <img src="logo.svg" alt="Wikimedia logo." width="32" height="32" />
  <label>
    <input type="search" />
    Search for words in articles
  </label>
</div>

如要將這個 div 移至標題列,必須採用某些 CSS:

.search {
  /* Make sure the `div` stays there, even when scrolling. */
  position: fixed;
  /**
   * Gradient, because why not. Endless opportunities.
   * The gradient ends in `#36c`, which happens to be the app's
   * `<meta name="theme-color" content="#36c">`.
   */
  background-image: linear-gradient(90deg, #36c, #131313, 33%, #36c);
  /* Use the environment variable for the left anchoring with a fallback. */
  left: env(titlebar-area-x, 0);
  /* Use the environment variable for the top anchoring with a fallback. */
  top: env(titlebar-area-y, 0);
  /* Use the environment variable for setting the width with a fallback. */
  width: env(titlebar-area-width, 100%);
  /* Use the environment variable for setting the height with a fallback. */
  height: env(titlebar-area-height, 33px);
}

您可以在下方螢幕截圖中查看這個程式碼的效果。標題列可完全回應。時間 調整 PWA 視窗的大小,標題列就會回應,就像組成一般 HTML 內容一樣。 事實上,確實這麼做

應用程式視窗,標題列中有搜尋列。
新的標題列已啟用且可回應。

決定標題列的哪些部分可拖曳

雖然上方的螢幕截圖顯示您已完成專案,但尚未完成。PWA 視窗是 無法拖曳 (在極小的區域除外),因為視窗控制按鈕不會拖曳 標題列的其他部分則包含搜尋小工具使用以下方式修正這個問題: app-region CSS 屬性,值為 drag。具體的情況下 除了 input 元素可拖曳以外,其他所有項目。

/* The entire search `div` is draggable… */
.search {
  -webkit-app-region: drag;
  app-region: drag;
}

/* …except for the `input`. */
input {
  -webkit-app-region: no-drag;
  app-region: no-drag;
}
敬上

有了這個 CSS,使用者就能照常拖曳 divimg、 或 label。只有 input 元素為互動式,因此可輸入搜尋查詢。

特徵偵測

可偵測視窗控制項重疊狀態的支援,方法是測試是否存在 windowControlsOverlay:

if ('windowControlsOverlay' in navigator) {
  // Window Controls Overlay is supported.
}

使用 windowControlsOverlay 查詢視窗控制區域

目前程式碼存在一個問題:在某些平台上,視窗控制項出現在右側 以及位於左側更糟糕的是,「三點」Chrome 選單將變更 位置則視廣告平台而定。換句話說,線性漸層背景圖片 動態調整以便在 #131313maroonmaroon#131313maroon 執行,讓執行作業 融入標題列的 maroon 背景顏色 (取決於 <meta name="theme-color" content="maroon">。這可以藉由查詢 navigator.windowControlsOverlay 屬性的 getTitlebarAreaRect() API。

if ('windowControlsOverlay' in navigator) {
  const { x } = navigator.windowControlsOverlay.getTitlebarAreaRect();
  // Window controls are on the right (like on Windows).
  // Chrome menu is left of the window controls.
  // [ windowControlsOverlay___________________ […] [_] [■] [X] ]
  if (x === 0) {
    div.classList.add('search-controls-right');
  }
  // Window controls are on the left (like on macOS).
  // Chrome menu is right of the window controls overlay.
  // [ [X] [_] [■] ___________________windowControlsOverlay [⋮] ]
  else {
    div.classList.add('search-controls-left');
  }
} else {
  // When running in a non-supporting browser tab.
  div.classList.add('search-controls-right');
}

比起之前,系統不會直接在 .search 類別 CSS 規則中加入背景圖片, 修改過的程式碼現在會使用以上程式碼動態設定的兩個類別。

/* For macOS: */
.search-controls-left {
  background-image: linear-gradient(90deg, #36c, 45%, #131313, 90%, #36c);
}

/* For Windows: */
.search-controls-right {
  background-image: linear-gradient(90deg, #36c, #131313, 33%, #36c);
}

判斷是否要顯示視窗控制項重疊

無論在何種情況下,標題列區域都不會顯示視窗控制項疊加層。期間 如果瀏覽器不支援視窗控制項重疊功能,就不會顯示在這類瀏覽器上 也不會有 PWA。如要偵測這種情況,您可以 查詢 windowControlsOverlayvisible 屬性:

if (navigator.windowControlsOverlay.visible) {
  // The window controls overlay is visible in the title bar area.
}
敬上

您也可以在 JavaScript 和/或 CSS 中使用 display-mode 媒體查詢:

// Create the query list.
const mediaQueryList = window.matchMedia('(display-mode: window-controls-overlay)');

// Define a callback function for the event listener.
function handleDisplayModeChange(mql) {
  // React on display mode changes.
}

// Run the display mode change handler once.
handleDisplayChange(mediaQueryList);

// Add the callback function as a listener to the query list.
mediaQueryList.addEventListener('change', handleDisplayModeChange);
@media (display-mode: window-controls-overlay) { 
  /* React on display mode changes. */ 
}

在幾何圖形變更時收到通知

使用 getTitlebarAreaRect() 查詢視窗控制項重疊區域即可達到一次性要求 例如根據視窗控制項的位置設定正確的背景圖片 則需要更精細的控制選項舉例來說,其中一種用途是 根據可用空間調整視窗控制項重疊顯示效果,並直接在視窗中加入笑話 並在有足夠空間時重疊顯示控制項。

視窗控制項的重疊區域與縮短的文字。
標題列控制項已根據窄視窗進行調整。

只要訂閱 navigator.windowControlsOverlay.ongeometrychange,或是針對 geometrychange 事件。只有在視窗控制項疊加層顯示時,才會觸發此事件, 在 navigator.windowControlsOverlay.visibletrue 時。

const debounce = (func, wait) => {
  let timeout;
  return function executedFunction(...args) {
    const later = () => {
      clearTimeout(timeout);
      func(...args);
    };
    clearTimeout(timeout);
    timeout = setTimeout(later, wait);
  };
};

if ('windowControlsOverlay' in navigator) {
  navigator.windowControlsOverlay.ongeometrychange = debounce((e) => {
    span.hidden = e.titlebarAreaRect.width < 800;
  }, 250);
}

除了將函式指派給 ongeometrychange,您也可以新增事件監聽器為 windowControlsOverlay,如下所示。您可以參閱 MDN

navigator.windowControlsOverlay.addEventListener(
  'geometrychange',
  debounce((e) => {
    span.hidden = e.titlebarAreaRect.width < 800;
  }, 250),
);

在分頁和不支援的瀏覽器上執行時的相容性

請考慮以下兩種情況:

  • 支援「視窗控制項」重疊效果的瀏覽器中執行應用程式時, 瀏覽器分頁顯示應用程式的情形
  • 不支援視窗控制項重疊的瀏覽器中執行應用程式時,

在這兩種情況下,系統預設會使用視窗控制項所建立的 HTML 重疊廣告會以內嵌方式顯示,就像一般 HTML 內容和 env() 變數一樣備用值 就會啟動。在支援的瀏覽器上,您也可以選擇不顯示 檢查疊加層的 visible 屬性,以及 就會回報 false,並隱藏該 HTML 內容。

在瀏覽器分頁中執行的 PWA,其內文重疊顯示視窗控制項。
在舊版瀏覽器中,標題列的控制項可以輕鬆顯示在內文中。

提醒您,系統不支援的瀏覽器 "display_override" 網頁應用程式資訊清單屬性,或無法識別 "window-controls-overlay",並根據備用鏈使用下一個可能的值 例如 "standalone"

以獨立模式執行的 PWA,且內文會顯示視窗控制項。
在舊版瀏覽器中,標題列的控制項可以輕鬆顯示在內文中。

使用者介面注意事項

雖然您可能正在嘗試,但我們不建議在「視窗控制項」重疊區域建立傳統下拉式選單。否則將違反 macOS 的設計指南、 使用者期望在哪個平台看到選單列 (系統提供選單列,以及 自訂小工具)。

如果您的應用程式提供全螢幕體驗,請審慎考量其是否合適 ,將視窗控制項重疊,納入全螢幕檢視中。您可能會 而且想要重新排列版面配置 onfullscreenchange敬上 事件。

示範

我建立了一個可用於示範的示範 不同支援和不支援的瀏覽器,以及已安裝和未安裝狀態的瀏覽器。適用對象 因此您必須安裝應用程式才能實際體驗 Window Control Overlay 體驗。請見下方兩張螢幕截圖,呈現結果。 您可以在 Glitch 取得應用程式的原始碼

Wikimedia 精選內容示範應用程式,其中有「視窗控制項」重疊顯示。
試用版應用程式可供實驗使用。

視窗控制項疊加層中的搜尋功能完全正常運作:

Wikimedia 精選內容示範應用程式,其中設有「視窗控制項」重疊顯示,並主動搜尋「cleopa...」一詞醒目顯示包含相符字詞「Cleopatra」的文章。
使用「視窗控制項重疊」的搜尋功能。

安全性考量

Chromium 團隊根據核心原則,設計並實作 Window Control Overlay API 定義,包括控管強大的 Web Platform 功能存取權,包括使用者 掌控權、透明度和人體工學

假冒

讓網站在標題列的部分控制權下,讓開發人員有更多空間可以假冒內容 過去是受到瀏覽器控制的信任區域目前在 Chromium 瀏覽器中為獨立瀏覽器 模式會在初始啟動時顯示標題列,並在左側顯示標題 右側頁面的來源 (後方是「設定和其他功能」按鈕和視窗) 控制項)。並在幾秒後,原始文字就會消失。如果瀏覽器設定為由右至左 (RTL) 語言,這個版面配置會翻轉,將原始文字顯示在左側。系統隨即會開啟 如果來源和目的地之間的邊框間距不足,則重疊的視窗控制項會重疊以假冒來源。 右側邊緣。例如,來源「evil.ltd」可附加至受信任的 網站「google.com」,讓使用者誤以認為這個來源值得信賴。這項計畫是 來源文字,可讓使用者瞭解應用程式原意,並確保其與應用程式的 期望。如果是 RTL 設定的瀏覽器,來源右側必須有足夠邊框間距 文字,防止惡意網站透過可信任的來源附加不安全的來源。

數位指紋採集

啟用視窗控制項重疊和可拖曳區域不會造成 功能偵測以外的隱私權疑慮。但由於 視窗控制按鈕在各種作業上的大小和位置 系統 navigator.windowControlsOverlay.getTitlebarAreaRect() 方法會傳回 DOMRect 其位置和維度可顯示作業系統的相關資訊 瀏覽器的狀態開發人員目前可探索 OS 擷取的資訊,但由於數位指紋採集疑慮 討論凍結通用 Analytics 字串及統合作業系統版本的相關討論。另有 不斷調整設定,以瞭解使用者存取網站的頻率 視窗控制項的大小會隨著各平台變更, 這些 API 在各個 OS 版本中都是相當穩定的 有助於觀察子 OS 版本雖然這可能是 指紋辨識問題,僅適用於採用自訂的已安裝 PWA 標題列功能,且不適用於一般瀏覽器使用情況。此外, navigator.windowControlsOverlay API 將無法再於下列對象使用 嵌入 PWA 中的 iframe。

在 PWA 中瀏覽至不同的來源,會導致網頁改回一般的獨立版本 即使其符合上述條件,也會在重疊視窗中啟動。 這種做法是為了容納前往不同來源導覽時顯示的黑色長條。更新後 返回原始來源時,系統會再次使用視窗控制項重疊顯示效果。

非來源導覽的黑色網址列。
使用者前往其他來源時,畫面上會顯示黑色長條。

意見回饋

Chromium 團隊想瞭解你的 Window Control Overlay API 使用體驗。

請與我們分享 API 設計

您覺得這個 API 有什麼不如預期的運作方式?或者缺少某些方法 需要實現什麼構想?對安全性有任何疑問或意見 以及模型在對應的 GitHub 存放區上提出規格問題,或將您的想法新增至 現有的問題。

回報導入問題

您發現 Chromium 實作錯誤嗎?還是採用與規格不同? 前往 new.crbug.com 回報錯誤。請務必盡量提供詳細資料 重現問題的簡單操作說明,然後在「Components」(元件) 中輸入 UI>Browser>WebAppInstalls 方塊。Glitch 有便捷的報復工具,

顯示對 API 的支援

您是否打算使用 Window Control Overlay API?你的公開支援能協助 Chromium 團隊 。

傳送 Tweet 並告知 @ChromiumDev #WindowControlsOverlay敬上 ,並告訴我們你使用哪些位置和方式。

實用連結

特別銘謝

Window Control Overlay 已實作 並由 Microsoft Edge 團隊的 Amanda Baker。 本文經過 Joe MedleyKenneth Rohde Christiansen。主頁橫幅製作者: 在 Unsplash 上找到 Sigmund