Webエンジニア向けプログラミング解説動画をYouTubeで配信中!
▶ チャンネル登録はこちら

【ITニュース解説】How I implemented Picture-in-Picture in React (with full code + tips)

2025年10月05日に「Dev.to」が公開したITニュース「How I implemented Picture-in-Picture in React (with full code + tips)」について初心者にもわかりやすく解説しています。

作成日: 更新日:

ITニュース概要

Reactアプリに「Document Picture-in-Picture (PiP)」を実装する方法を解説。Chrome 116+で使えるこの新機能は、動画だけでなくタイマーやチャットなど、任意のReactコンポーネントを独立した小さな浮動ウィンドウで表示できる。記事には具体的なコード例と実装のコツが書かれており、導入は比較的簡単だ。

ITニュース解説

ウェブアプリケーション開発の新しい技術として、「Document Picture-in-Picture(PiP)」APIが注目されている。これは、従来の動画再生におけるPiP機能とは異なり、ウェブページ上の任意のHTMLコンテンツやReactコンポーネントを、画面の隅に表示される小さなフローティングウィンドウに表示できる機能である。まるでデスクトップアプリのように、ユーザーが他のタブに切り替えたり、別のアプリケーションを使ったりしている間も、表示された内容を確認し続けられる点が大きな特徴だ。

このDocument PiPは、ChromeやEdgeのバージョン116以降のブラウザで利用可能になった。具体的な利用例としては、タスクを進行中に常に表示しておきたいタイマー、ウェブ会議中にメッセージを送受信できるチャットボックス、あるいは音楽プレーヤーやメモ帳、天気予報などのミニウィジェットなどが考えられる。メインのブラウザタブから独立して機能する小さなUI(ユーザーインターフェース)を提供することで、ユーザーの利便性を大きく向上させることが期待される。

しかし、この新しいAPIにはいくつかの制限がある。まず、対応しているブラウザが現状ではChromeとEdgeのChromium系ブラウザに限られており、SafariやFirefoxでは利用できない。また、同時に開けるPiPウィンドウは一つだけである。複数のフローティングウィンドウを同時に表示することはできないため、UI設計時にはこの点を考慮する必要がある。PiPウィンドウ内ではクリックやキーボード入力といったユーザーとのインタラクションが可能だが、ウィンドウ自体は小さいため、表示するUIは最小限かつシンプルに保つことが求められる。

記事では、このDocument PiPをJavaScriptのフレームワークであるReactと、モダンな開発環境であるViteを使って実装する方法が解説されている。中心となるのは、useDocumentPiPというカスタムフックだ。これは、PiPウィンドウの開閉、現在の状態(開いているか閉じているか)、そしてこの機能がブラウザでサポートされているかどうかを管理するための再利用可能なロジックをまとめたものである。

このカスタムフックの内部では、ブラウザが提供するdocumentPictureInPicture.requestWindowというAPIを呼び出して、新しいPiPウィンドウを作成する。このAPIは非同期で動作し、新しいウィンドウが準備されるのを待ってから処理を進める。新しいウィンドウが開かれると、そのウィンドウのHTMLドキュメントに対して、メインのウェブページで使われているCSSスタイルをコピーして適用する処理が行われる。これは、PiPウィンドウに表示される内容が、メインのページと同じデザインで表示されるようにするためである。

スタイルが適用された後、PiPウィンドウのドキュメント内に、Reactコンポーネントをレンダリングするためのコンテナ要素が作成される。そして、React 18から導入されたcreateRootという機能を使って、このコンテナ要素に、開発者がPiPウィンドウに表示したい任意のReactコンポーネント(例えばタイマーコンポーネント)を埋め込む。これにより、PiPウィンドウ内で独立したReactアプリケーションの一部が実行される形となる。

PiPウィンドウがユーザーによって閉じられたり、何らかの理由で非表示になったりした際には、そのイベントを検知して、PiPウィンドウ内のReactコンポーネントをアンマウントし、関連するリソースを解放するクリーンアップ処理が自動的に実行されるように設定されている。これは、メモリリークを防ぎ、アプリケーションの安定性を保つ上で非常に重要である。

このカスタムフックを使うことで、PictureInPictureButtonというコンポーネントが実装されている。このボタンは、useDocumentPiPフックから提供される開閉機能を利用し、ユーザーがクリックするとPiPウィンドウを開いたり閉じたりする。もしブラウザがDocument PiPをサポートしていない場合は、ボタン自体が表示されないように制御されており、ユーザーにとって不必要なUIを表示しない配慮がなされている。

実装中に遭遇しがちな問題点とその解決策も示されている。例えば、PiPウィンドウ内でCSSが正しく適用されない場合がある。これは、スタイルシートが異なるオリジン(ドメイン)から読み込まれている場合に発生することがあり、その場合はスタイルシートを直接コピーするのではなく、<link>タグとしてPiPウィンドウのドキュメントに再挿入することで対処できる。また、PiPウィンドウに内容が表示されず空白になる場合は、documentPictureInPicture.requestWindowの呼び出しが完了する前にReactコンポーネントをレンダリングしようとしている可能性があり、非同期処理を適切に待つ(awaitを使う)ことや、React 18のcreateRootを正しく使うことで解決できる。複数のPiPウィンドウを同時に開けないというAPIの制限に対しては、カスタムフックが提供するisOpenの状態を使って、すでにウィンドウが開いている場合は新しいウィンドウを開かないように制御することで対処する。

このDocument PiP機能はまだ新しい技術であり、テストの重要性も強調されている。ブラウザの設定でDocument Picture-in-Picture APIが有効になっていることを確認し、実際にボタンをクリックしてPiPウィンドウが開くか、タブを切り替えてもウィンドウが画面上に保持されるか、そしてEscキーや手動でウィンドウを閉じた際に正常に動作が終了するか、といった項目を丁寧に確認することが安定したアプリケーション提供には不可欠である。

Document PiPの実装は予想よりも簡単であり、現状ではブラウザの対応が限定的であるものの、タイマーやウィジェット、チャットツールなど、特定のユースケースにおいては非常に実用的で便利な機能であることが示されている。これはウェブアプリケーションが、よりデスクトップアプリケーションに近いユーザー体験を提供できる可能性を秘めていることを意味する。

関連コンテンツ

関連IT用語