ページ可視性 API

ページ可視性 API (Page Visibility API) では、現在ページが見えているかどうかを調べる機能とともに、文書が表示されたり非表示になったりした時を監視することができるイベントを提供します。

これは特に、文書が表示されていない時に不必要なタスクの実行を抑止することで、リソースを節約したり実行効率を上げたりするために特に有用です。

概念と使用法

ユーザーがウィンドウを最小化したり他のタブに切り替えたりした時、 API は visibilitychange イベントを送信してリスナーにページの状態が変化したことを知らせます。イベントを検出していくつかの操作を実行したり、様々な動作をしたりすることができます。例えば、ウェブアプリで動画を再生している場合、ユーザーがタブをバックグラウンドにした場合に動画を一時停止させ、ユーザーがこのタブに戻ったときに再生を再開させたりすることができます。ユーザーは動画の位置に迷うことがなく、動画の音声が新しく前景になったタブの音声を邪魔せず、ユーザーがその間に動画を見落とすことがなくなります。

<iframe> の可視状態は、親文書と同じになります。 CSS プロパティにより (display: none; のように) <iframe> を隠しても可視性イベントは発生せず、またフレームに含まれる文書の状態も変わりません。

使用例

ページ可視性 API の使用例をいくつか考えてみましょう。

  • 画像のスライドショーがあるサイトで、ユーザーが見ていない間に次のスライドに進むべきではないもの
  • 情報をダッシュボードに表示するアプリケーションで、ページが見えていないときは更新情報をサーバーへ問い合わせてほしくないもの
  • 正確なページビューをカウントできるよう、ページがプリレンダリングされている状態を検出したい。
  • 端末がスタンバイモードである (ユーザーが電源ボタンを押して、画面を消灯している) ときに、音声を止めたいサイト。

以前、開発者はこれを検出するために不完全な代替手段を使用していました。例えばウィンドウで blur および focus イベントを監視することで、ページがアクティブではないときを知る助けになりますが、ページがユーザーから隠された状態であることは知らせてくれません。ページ可視性 API はこれを解決します。

メモ: onblur および onfocus はユーザーがウィンドウを切り替えたことを教えてくれますが、非表示にしたという意味になるとは限りません。ページが非表示になるのは、ユーザーがタブを切り替えたり、タブを含むブラウザーウィンドウを最小化したりした時だけです。

バックグラウンドページのパフォーマンスを向上させるためのポリシー

ページ可視性 API とは別に、ユーザーエージェントは通常、バックグラウンドまたは隠されたタブのパフォーマンスへの影響を緩和するために、いくつかのポリシーを持っています。これには次のようなものがあります。

  • ほとんどのブラウザーは、パフォーマンスとバッテリーライフを改善するために、バックグラウンドのタブや非表示の <iframe> への requestAnimationFrame() コールバックの送信を停止します。
  • setTimeout() などのタイマーは、バックグラウンド/非アクティブなタブでは、パフォーマンスを向上させるために遅延されます。詳しくは、遅延が指定値より長い理由を参照してください。
  • ブラウザーは、予算ベースのバックグラウンドタイムアウトの調整機能を実装しています。これは現代のブラウザー間で類似した方法で処理され、詳細は以下のとおりです。
    • Firefox では、バックグラウンドタブのウィンドウは、それぞれ自分自身でミリ秒単位の時間予算(最大値で +50ms、最小値で -150ms)を保有します。 Chrome は、予算が秒単位で指定されることを除けば、とてもよく似ています。
    • ウィンドウは、ウィンドウタイマーに指定されたのと同じ遅延調整ルールで、 30 秒後に調整されます(ここでも、遅延が指定値より長い理由を参照してください)。Chrome では、この値は 10 秒です。
    • タイマータスクは、予算が非負のときのみ許可されます。
    • タイマーのコードの実行が完了すると、その実行に要した時間がウィンドウのタイムアウト予算から差し引かれます。
    • 予算は、Firefox、Chrome ともに、 1 秒間に 10 ミリ秒の割合で再生成されます。

一部のプロセスは、この調整動作から除外されます。このような場合、ページ可視性 API を使用して、タブが非表示になっている間のパフォーマンスへの影響を軽減することができます。

  • 音声を再生しているタブはフォアグラウンドとみなされ、調整されることはありません。
  • リアルタイムのネットワーク接続(WebSocketWebRTC)を使用しているコードを実行しているタブは、これらの接続がタイムアウトして予期せず取得されるのを避けるために、調整が解除されます。
  • IndexedDB のプロセスもタイムアウトを避けるため、調整なしのままになります。

他のインターフェイスの拡張

インスタンスプロパティ

ページ可視性 API は、以下のプロパティを Document インターフェイスに追加します。

Document.hidden 非推奨 読取専用

ページがユーザーから隠された状態であると思われる場合に true を、そうでない場合に false を返します。

Document.visibilityState 読取専用

文字列で、文書の現在の可視状態を示します。取りうる値は以下の通りです。

visible

このページのコンテンツは、少なくとも部分的に可視状態です。実際は、最小化されていないウィンドウのフォアグラウンドのタブにページがあることを意味します。

hidden

このページのコンテンツはユーザーから見えていません。実際は、文書がバックグラウンドのタブか最小化されているウィンドウにある、あるいは OS のスクリーンがロックされていることを意味します。

イベント

ページ可視性 API は、以下のイベントを Document インターフェイスに追加します。

visibilitychange

タブの内容が可視状態または非表示になった時に発行されます。

ページが非表示になると音声を一時停止

この例では、ユーザーが異なる形に切り替えたときに音声を一時停止し、元に戻したときに再生します。

HTML

html
<audio
  controls
  src="https://mdn.github.io/webaudio-examples/audio-basics/outfoxing.mp3"></audio>

JavaScript

js
const audio = document.querySelector("audio");

// Handle page visibility change:
// - If the page is hidden, pause the video
// - If the page is shown, play the video
document.addEventListener("visibilitychange", () => {
  if (document.hidden) {
    audio.pause();
  } else {
    audio.play();
  }
});

結果

音声を再生してから、異なる形のタブに切り替えて、もう一度再生してみてください。

仕様書

Specification
HTML Standard
# dom-document-visibilitystate

ブラウザーの互換性

BCD tables only load in the browser