ウィンドウ コントロールの横にあるタイトルバー領域を使用して、PWA をアプリのように見せることができます。
PWA をアプリのように感じさせるという記事を覚えていらっしゃる方は、アプリのようなエクスペリエンスを実現するための戦略として、アプリのタイトルバーをカスタマイズする方法について説明したことを思い出されるかもしれません。macOS の Podcasts アプリで表示される例を次に示します。

ここで、ポッドキャストはブラウザで実行されないプラットフォーム固有の macOS アプリであるため、ブラウザのルールに従う必要がなく、自由に動作できると反論したくなるかもしれません。確かにそうですが、このたび、この記事のテーマである Window Controls Overlay 機能が導入され、PWA で同様のユーザー インターフェースを作成できるようになります。
ウィンドウ コントロール オーバーレイのコンポーネント
ウィンドウ コントロール オーバーレイは、次の 4 つのサブ機能で構成されています。
- ウェブアプリ マニフェストの
"display_override"
フィールドの"window-controls-overlay"
値。 - CSS 環境変数
titlebar-area-x
、titlebar-area-y
、titlebar-area-width
、titlebar-area-height
。 - 以前は独自仕様だった CSS プロパティ
-webkit-app-region
を、ウェブ コンテンツ内のドラッグ可能な領域を定義するapp-region
プロパティとして標準化しました。 window.navigator
のwindowControlsOverlay
メンバーを介してウィンドウ コントロール領域をクエリし、回避するメカニズム。
ウィンドウ コントロール オーバーレイとは
タイトルバー領域とは、ウィンドウ コントロール(最小化、最大化、閉じるなどのボタン)の左側または右側のスペースを指し、多くの場合、アプリケーションのタイトルが含まれています。ウィンドウ コントロール オーバーレイを使用すると、プログレッシブ ウェブ アプリケーション(PWA)で、既存の全幅のタイトルバーをウィンドウ コントロールを含む小さなオーバーレイに置き換えることで、アプリのような操作感を実現できます。これにより、デベロッパーは、以前はブラウザが制御していたタイトルバー領域にカスタム コンテンツを配置できます。
現在のステータス
Step | ステータス |
---|---|
1. 説明を作成する | 完了 |
2. 仕様の最初のドラフトを作成する | 完了 |
3. フィードバックを収集してデザインを反復 | 作成中 |
4. オリジン トライアル | 完了 |
5. リリース | 完了(Chromium 104) |
ウィンドウ コントロール オーバーレイの使用方法
ウェブアプリ マニフェストに window-controls-overlay
を追加する
プログレッシブ ウェブアプリでウィンドウ コントロール オーバーレイを有効にするには、ウェブアプリ マニフェストで "window-controls-overlay"
をプライマリ "display_override"
メンバーとして追加します。
{
"display_override": ["window-controls-overlay"]
}
ウィンドウ コントロール オーバーレイは、次のすべての条件が満たされた場合にのみ表示されます。
- アプリはブラウザではなく、別の PWA ウィンドウで開きます。
- マニフェストには
"display_override": ["window-controls-overlay"]
が含まれています。(その後は他の値も許可されます)。 - PWA がデスクトップ オペレーティング システムで実行されている。
- 現在のオリジンが、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 コンテンツで構成されているかのように反応します。実際、タイトルバーは HTML コンテンツで構成されています。

タイトルバーのどの部分をドラッグ可能にするかを決定する
上記のスクリーンショットでは完了したように見えますが、まだ完了していません。ウィンドウ コントロール ボタンはドラッグ領域ではなく、タイトルバーの残りの部分は検索ウィジェットで構成されているため、PWA ウィンドウは(ごく一部を除いて)ドラッグできなくなります。この問題を解決するには、drag
の値を持つ app-region
CSS プロパティを使用します。具体的なケースでは、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 を配置すると、ユーザーは通常どおり div
、img
、label
をドラッグしてアプリ ウィンドウをドラッグできます。input
要素のみがインタラクティブなので、検索クエリを入力できます。
特徴検出
Window Controls Overlay のサポートは、windowControlsOverlay
の存在をテストすることで検出できます。
if ('windowControlsOverlay' in navigator) {
// Window Controls Overlay is supported.
}
windowControlsOverlay
を使用してウィンドウ コントロール領域をクエリする
これまでのコードには 1 つ問題があります。一部のプラットフォームではウィンドウ コントロールが右側にあり、他のプラットフォームでは左側にあります。さらに、プラットフォームに応じて Chrome のその他メニューの位置も変わります。つまり、<meta name="theme-color" content="maroon">
によって決定されるタイトルバーの maroon
背景色に溶け込むように、線形グラデーションの背景画像を #131313
→maroon
または maroon
→#131313
→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 ルールに背景画像を直接指定するのではなく、上記のコードで動的に設定される 2 つのクラスを使用しています。
/* 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 がタブで実行されている場合も表示されません。この状況を検出するには、windowControlsOverlay
の visible
プロパティをクエリします。
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()
でウィンドウ コントロールのオーバーレイ領域をクエリすることは、ウィンドウ コントロールの位置に基づいて正しい背景画像を設定するなどの 1 回限りの処理には十分ですが、他のケースではより細かい制御が必要になります。たとえば、利用可能なスペースに基づいてウィンドウ コントロールのオーバーレイを調整し、十分なスペースがある場合はウィンドウ コントロールのオーバーレイにジョークを追加する、といったユースケースが考えられます。

navigator.windowControlsOverlay.ongeometrychange
をサブスクライブするか、geometrychange
イベントのイベント リスナーを設定することで、ジオメトリの変更を通知できます。このイベントは、ウィンドウ コントロール オーバーレイが表示されている場合、つまり navigator.windowControlsOverlay.visible
が true
の場合にのみ発生します。
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
にイベント リスナーを追加することもできます。この 2 つの違いについては、MDN をご覧ください。
navigator.windowControlsOverlay.addEventListener(
'geometrychange',
debounce((e) => {
span.hidden = e.titlebarAreaRect.width < 800;
}, 250),
);
タブで実行する場合やサポートされていないブラウザで実行する場合の互換性
考慮すべきケースは次の 2 つです。
- Window Controls Overlay をサポートしているブラウザでアプリが実行されているが、アプリがブラウザタブで使用されている場合。
- Window Controls Overlay をサポートしていないブラウザでアプリが実行されている場合。
どちらの場合も、デフォルトでは、ウィンドウ コントロール オーバーレイ用に構築された HTML は通常の HTML コンテンツのようにインラインで表示され、env()
変数のフォールバック値が位置決めに使用されます。対応ブラウザでは、オーバーレイの visible
プロパティをチェックし、false
が返された場合は、ウィンドウ コントロール オーバーレイ用に指定された HTML を表示しないようにすることもできます。

サポートしていないブラウザでは、"display_override"
ウェブアプリ マニフェスト プロパティがまったく考慮されないか、"window-controls-overlay"
が認識されないため、フォールバック チェーンに従って次の可能な値("standalone"
など)が使用されます。

UI に関する考慮事項
ウィンドウ コントロール オーバーレイ領域に従来のプルダウン メニューを作成することは可能ですが、おすすめしません。そうすると、ユーザーが画面上部にメニューバー(システム提供のものとカスタムのもの両方)を期待するプラットフォームである macOS の設計ガイドラインに違反することになります。
アプリで全画面表示が提供される場合は、ウィンドウ コントロール オーバーレイを全画面表示の一部にすることが適切かどうかを慎重に検討してください。onfullscreenchange
イベントが発生したときにレイアウトを再配置することがあります。
デモ
さまざまな対応ブラウザと非対応ブラウザ、インストール済みと未インストールの状態で試せるデモを作成しました。実際のウィンドウ コントロール オーバーレイ エクスペリエンスを利用するには、アプリをインストールする必要があります。以下に、期待されるエクスペリエンスの 2 つのスクリーンショットを示します。アプリのソースコードは Glitch で入手できます。

ウィンドウ コントロールのオーバーレイの検索機能は完全に機能します。

セキュリティ上の考慮事項
Chromium チームは、強力なウェブ プラットフォーム機能へのアクセスの制御で定義されているユーザー制御、透明性、人間工学などの基本原則を使用して、Window Controls Overlay API を設計、実装しました。
なりすまし
サイトにタイトルバーの制御を部分的に許可すると、デベロッパーが以前は信頼できるブラウザ制御の領域でコンテンツをスプーフィングする余地が生まれます。現在、Chromium ブラウザのスタンドアロン モードにはタイトルバーが含まれており、初回起動時には、左側にウェブページのタイトル、右側にページのオリジンが表示されます(その後に [設定など] ボタンとウィンドウ コントロールが続きます)。数秒後に元のテキストが消えます。ブラウザが右から左(RTL)の言語に設定されている場合、このレイアウトは反転され、元のテキストが左側に表示されます。これにより、ウィンドウ コントロール オーバーレイが開き、オーバーレイの右端とオリジンとの間に十分なパディングがない場合にオリジンをスプーフィングします。たとえば、送信元「evil.ltd」に信頼できるサイト「google.com」が追加され、ユーザーが送信元を信頼できると信じてしまう可能性があります。この元のテキストは、ユーザーがアプリの出所を把握し、期待どおりであることを確認できるように、そのまま残す予定です。RTL が構成されたブラウザでは、悪意のあるウェブサイトが安全でないオリジンを信頼できるオリジンに追加するのを防ぐために、オリジン テキストの右側に十分なパディングが必要です。
フィンガープリント
ウィンドウ コントロールのオーバーレイとドラッグ可能な領域を有効にしても、機能検出以外のプライバシー上の大きな問題は発生しません。ただし、オペレーティング システムによってウィンドウ コントロール ボタンのサイズと位置が異なるため、navigator.
メソッドは、ブラウザが実行されているオペレーティング システムに関する情報を明らかにする位置と寸法を持つ DOMRect
を返します。現在、デベロッパーはユーザー エージェント文字列から OS を検出できますが、フィンガープリントに関する懸念から、UA 文字列のフリーズと OS バージョンの統合について議論されています。ブラウザ コミュニティでは、ウィンドウ コントロール オーバーレイのサイズがプラットフォーム間でどの程度の頻度で変化するかを把握するための取り組みが進行中です。現在の仮定では、これらのサイズは OS バージョン間でかなり安定しているため、マイナー OS バージョンの観察には役立たないと考えられています。これはフィンガープリントの問題になる可能性がありますが、カスタム タイトルバー機能を使用するインストール済み PWA にのみ適用され、一般的なブラウザの使用には適用されません。また、navigator.
API は PWA 内に埋め込まれた iframe では利用できません。
ナビゲーション
PWA 内で別のオリジンに移動すると、上記の条件を満たし、ウィンドウ コントロール オーバーレイで起動された場合でも、通常のスタンドアロン タイトルバーに戻ります。これは、別のオリジンに移動したときに表示される黒いバーに対応するためです。元のオリジンに戻ると、ウィンドウ コントロール オーバーレイが再び使用されます。

フィードバック
Chromium チームは、Window Controls Overlay API の使用感について皆様のご意見をお待ちしています。
API 設計について教えてください
API が想定どおりに動作しない点はありますか?アイデアを実装するために必要なメソッドやプロパティが不足している場合はどうすればよいですか?セキュリティ モデルについてご質問やご意見がある場合は、対応する GitHub リポジトリで仕様に関する問題を報告するか、既存の問題に意見を追加します。
実装に関する問題を報告する
Chromium の実装でバグが見つかりましたか?それとも、実装が仕様と異なるのでしょうか?new.crbug.com でバグを報告します。できるだけ詳細な情報、再現手順を記載し、[Components](コンポーネント)ボックスに UI>Browser>WebAppInstalls
と入力してください。
API のサポートを表示する
Window Controls Overlay API を使用する予定はありますか?公開サポートは、Chromium チームが機能の優先順位を決定するのに役立ち、他のブラウザ ベンダーにサポートの重要性を示すことができます。
#WindowControlsOverlay
ハッシュタグを付けて @ChromiumDev にツイートし、どこでどのように使用しているかをお知らせください。
関連情報
謝辞
Window Controls Overlay は、Microsoft Edge チームの Amanda Baker によって実装され、指定されました。この記事は、Joe Medley と Kenneth Rohde Christiansen によってレビューされました。ヒーロー画像: Unsplash の Sigmund。