Preferreds-reduced-motion: 動きが少ないほうがよい場合もあります

prefers-reduced-motion メディアクエリは、ユーザーがオペレーティング システムに対してアニメーションやモーションの使用量を最小限に抑えるようリクエストしたかどうかを検出します。

装飾的なアニメーションやトランジションを好まない人もいます。また、視差スクロールやズーム効果などを見ると、乗り物酔いを起こす人もいます。ユーザー設定のメディアクエリ prefers-reduced-motion を使用すると、この設定を指定したユーザー向けに、サイトのモーションを減らしたバリエーションをデザインできます。

Browser Support

  • Chrome: 74.
  • Edge: 79.
  • Firefox: 63.
  • Safari: 10.1.

Source

現実世界とウェブ上の動きが多すぎる

先日、子どもたちとスケートに行きました。太陽が輝く素敵な日でした。スケートリンクは人でいっぱいでした ⛸。ただ、私は人混みが苦手です。目標が多すぎて、何にも集中できず、迷子になったような気分で、視覚的な過負荷を感じます。まるでアリ塚を見つめているようです。🐜

アイススケートをする人々の足の群衆。
現実世界での視覚情報の過多。

ウェブでも同様のことが起こることがあります。点滅する広告、凝ったパララックス効果、驚くような表示アニメーション、自動再生される動画など、ウェブはときに圧倒されることがあります。幸いなことに、現実世界とは異なり、この問題には解決策があります。CSS メディアクエリ prefers-reduced-motion を使用すると、モーションの低減を好むユーザー向けにページのバリエーションを作成できます。これには、動画の自動再生を控えること、純粋に装飾的な効果を無効にすること、特定のユーザー向けにページを完全に再設計することなど、さまざまなものが含まれます。

機能の説明に入る前に、ウェブでアニメーションがどのように使用されているかを振り返ってみましょう。必要に応じて、背景情報をスキップして、技術的な詳細に直接進むこともできます。

ウェブ上のアニメーション

アニメーションは、ユーザーにフィードバックを提供するために使用されることがよくあります。たとえば、アクションが受信されて処理中であることをユーザーに知らせるために使用されます。たとえば、ショッピング ウェブサイトでは、商品がアニメーションでサイトの右上隅にあるアイコンで表される仮想ショッピング カートに「飛んでいく」ように表示されます。

別のユースケースでは、スケルトン画面、コンテキスト メタデータ、低品質の画像プレビューを組み合わせて使用し、ユーザーの時間を多く占有することで、全体的なエクスペリエンスをより速く感じさせるというユーザーの認識をハッキングするためにモーションを使用します。ユーザーに何が起こるかを伝えながら、できるだけ早く読み込むことを目的としています。

最後に、アニメーション グラデーション、パララックス スクロール、背景動画など、装飾効果があります。多くのお客様はこのようなアニメーションを好んでいますが、気が散る、動作が遅くなるなどの理由で嫌うお客様もいます。最悪の場合、ユーザーは現実世界での体験と同じように乗り物酔いを起こす可能性もあります。そのため、このようなユーザーにとっては、アニメーションを減らすことは医学的に必要なことです。

運動誘発性前庭スペクトラム障害

一部のユーザーは、アニメーション コンテンツによって気が散ったり、吐き気を催したりすることがあります。たとえば、スクロール アニメーションでは、スクロールに関連付けられたメイン要素以外の要素が大きく動くと、前庭障害を引き起こす可能性があります。たとえば、パララックス スクロール アニメーションでは、背景要素が前景要素とは異なる速度で移動するため、前庭障害を引き起こす可能性があります。前庭(内耳)障害の反応には、めまい、吐き気、片頭痛などがあり、回復のために安静が必要になることもあります。

オペレーティング システムでのモーションの削除

多くのオペレーティング システムには、モーションの低減を優先する設定が以前から用意されています。次のスクリーンショットは、macOS Mojave の [動作を減らす] 設定と Android Pie の [アニメーションを削除] 設定を示しています。この設定をオンにすると、オペレーティング システムでアプリの起動アニメーションなどの装飾効果が使用されなくなります。アプリケーション自体もこの設定を尊重し、不要なアニメーションをすべて削除する必要があります。

[動作を減らす] チェックボックスがオンになっている macOS の設定画面。
[アニメーションを無効化] チェックボックスがオンになっている Android の設定画面。

ウェブでモーションを削除する

メディアクエリ レベル 5 では、モーションの低減に関するユーザー設定がウェブにも導入されています。メディアクエリを使用すると、作成者はレンダリングされるドキュメントとは無関係に、ユーザー エージェントまたはディスプレイ デバイスの値や機能をテストしてクエリできます。メディアクエリ prefers-reduced-motion は、ユーザーがオペレーティング システムの設定でアニメーションやモーションの使用量を最小限に抑えるように指定しているかどうかを検出するために使用されます。次の 2 つの値のいずれかになります。

  • no-preference: ユーザーが基盤となるオペレーティング システムで設定を行っていないことを示します。このキーワード値は、ブール値のコンテキストでは false として評価されます。
  • reduce: インターフェースの動きやアニメーションを最小限に抑える(できれば、不要な動きをすべて取り除く)ことを示すオペレーティング システム設定をユーザーが設定していることを示します。

CSS と JavaScript のコンテキストからメディアクエリを操作する

すべてのメディアクエリと同様に、prefers-reduced-motion は CSS コンテキストと JavaScript コンテキストから確認できます。

両方を説明するために、ユーザーにクリックしてほしい重要な登録ボタンがあるとします。目を引く「振動」アニメーションを定義できますが、ウェブの良き市民として、アニメーションを明示的に許可しているユーザーにのみ再生し、それ以外のユーザーには再生しません。それ以外のユーザーとは、アニメーションをオプトアウトしているユーザーや、メディアクエリを理解しないブラウザを使用しているユーザーなどです。

/*
  If the user has expressed their preference for
  reduced motion, then don't use animations on buttons.
*/
@media (prefers-reduced-motion: reduce) {
  button {
    animation: none;
  }
}

/*
  If the browser understands the media query and the user
  explicitly hasn't set a preference, then use animations on buttons.
*/
@media (prefers-reduced-motion: no-preference) {
  button {
    /* `vibrate` keyframes are defined elsewhere */
    animation: vibrate 0.3s linear infinite both;
  }
}

JavaScript で prefers-reduced-motion を操作する方法を説明するために、Web Animations API を使用して複雑なアニメーションを定義したとします。CSS ルールはユーザー設定が変更されるとブラウザによって動的にトリガーされますが、JavaScript アニメーションの場合は、変更を自分でリッスンし、実行中のアニメーションを手動で停止(またはユーザーが許可した場合は再開)する必要があります。

const mediaQuery = window.matchMedia('(prefers-reduced-motion: reduce)');
mediaQuery.addEventListener('change', () => {
  console.log(mediaQuery.media, mediaQuery.matches);
  // Stop JavaScript-based animations.
});

実際のメディアクエリを囲む括弧は必須です。

すべきでないこと
window.matchMedia('prefers-reduced-motion: reduce');
すべきこと
window.matchMedia('(prefers-reduced-motion: reduce)');

<picture> コンテキストからのメディアクエリの操作

興味深いユースケースとして、アニメーション AVIF、WebP、GIF の再生を media 属性に依存させることがあります。(prefers-reduced-motion: no-preference)true と評価される場合は、アニメーション バージョンを表示しても安全です。それ以外の場合は、静止画バージョンを表示します。

<picture>
  <!-- Animated versions. -->
  <source
    srcset="nyancat.avifs"
    type="image/avif"
    media="(prefers-reduced-motion: no-preference)"
  />
  <source
    srcset="nyancat.gif"
    type="image/gif"
    media="(prefers-reduced-motion: no-preference)"
  />
  <!-- Static versions. -->
  <img src="nyancat.png" alt="Nyan cat" width="250" height="250" />
</picture>

次の例をご覧ください。デバイスのモーション設定を切り替えて、違いを確認してみてください。

有名なニャン猫。

リクエスト時にユーザーの設定を検出する

Sec-CH-Prefers-Reduced-Motion クライアント ヒント ヘッダーを使用すると、サイトはリクエスト時にユーザーのモーション設定を任意で取得できるため、サーバーはパフォーマンス上の理由から適切な CSS をインライン化できます。

デモ

Rogério Vicente 氏の素晴らしい 🐈 HTTP ステータス猫をベースにしたデモを作成しました。まず、このジョークを理解してください。とても面白いので、しばらくお待ちします。それでは、デモをご紹介します。スクロールすると、HTTP ステータス猫が左右から交互に現れます。60 FPS のスムーズなアニメーションですが、前述のとおり、一部のユーザーはこれを好まないか、乗り物酔いのような症状を引き起こす可能性があります。そのため、デモは prefers-reduced-motion を尊重するようにプログラムされています。これは動的に機能するため、ユーザーは再読み込みすることなく、その場で設定を変更できます。ユーザーがモーションの低減を希望している場合、不要な表示アニメーションは削除され、通常のスクロール モーションのみが残ります。次のスクリーンキャストは、デモの動作を示しています。

prefers-reduced-motion デモアプリの動画

まとめ

ユーザー設定の尊重は最新のウェブサイトにとって重要であり、ウェブ デベロッパーがそれを実現できるように、ブラウザはますます多くの機能を公開しています。もう 1 つの例として、prefers-color-scheme があります。これは、ユーザーがライトモードとダークモードのどちらを好むかを検出します。prefers-color-scheme については、私の記事「Hello Darkness, My Old Friend 🌒」をご覧ください。

CSS ワーキング グループは、prefers-reduced-transparency(ユーザーが透明度の低下を希望しているかどうかを検出)、prefers-contrast(ユーザーが隣接する色のコントラストの増減をシステムにリクエストしているかどうかを検出)、inverted-colors(ユーザーが色の反転を希望しているかどうかを検出)など、より多くのユーザー設定メディアクエリを標準化しています。

(ボーナス)すべてのウェブサイトでモーションを抑制する

すべてのサイトが prefers-reduced-motion を使用するわけではありません。また、使用していても、ユーザーの好みに合うほどではないかもしれません。理由を問わず、すべてのウェブサイトでモーションを停止したい場合は、実際に停止できます。これを実現する方法の 1 つは、アクセスするすべてのウェブページに次の CSS を含むスタイルシートを挿入することです。この機能を可能にするブラウザ拡張機能がいくつかあります(自己責任で使用してください)。

@media (prefers-reduced-motion: reduce) {
  *,
  ::before,
  ::after {
    animation-delay: -1ms !important;
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
    background-attachment: initial !important;
    scroll-behavior: auto !important;
    transition-duration: 1ms !important;
    transition-delay: -1ms !important;
  }
}

この方法では、以前の CSS で、すべてのアニメーションとトランジションの期間が短すぎて認識できないほどに上書きされます。一部のウェブサイトは、正しく動作するためにアニメーションの実行に依存しているため(特定のステップが animationend イベントの発火に依存しているなど)、よりラジカルな animation: none !important; アプローチは機能しません。以前のハックでも、すべてのウェブサイトで成功するとは限りません(たとえば、Web Animations API を使用して開始されたモーションを停止することはできません)。そのため、破損に気づいたら必ず無効にしてください。

リソース

謝辞

Chrome に prefers-reduced-motion を実装し、Rob Dodson とともにこのドキュメントをレビューしてくれた Stephen McGruer に感謝します。