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

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

装飾的なアニメーションや遷移を好まないユーザーもいます。視差スクロールやズーム エフェクトなどが表示されると、乗り物酔いのような症状を感じるユーザーもいます。ユーザー設定メディア クエリ prefers-reduced-motion を使用すると、この設定を指定しているユーザー向けに、モーションを抑えたサイトのバリエーションを設計できます。

対応ブラウザ

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

ソース

現実世界やウェブでの動きが激しすぎる

先日、子供たちとアイススケートをしていました。晴天の下、アイスリンクは人でいっぱいでした ⛸。唯一の問題は、私は人混みに弱いことです。動くターゲットが非常に多いため、何にも集中できず、蟻塚 🐜? を見つめているような視覚的な過負荷を感じて、最終的に迷子になります。

アイススケートを履いた人々の足が並んでいる。
現実世界での視覚的な過負荷。

ウェブでも同様のことが起こることがあります。点滅する広告、派手なパララックス エフェクト、驚きのアニメーション、自動再生される動画など、ウェブはときに圧倒されるほど過剰な情報量になることがあります。幸い、現実世界とは異なり、その問題を解決する方法があります。CSS メディアクエリ prefers-reduced-motion を使用すると、デベロッパーは、モーションの抑制を好むユーザー向けにページのバリエーションを作成できます。たとえば、動画の自動再生を控えたり、純粋に装飾的な効果を無効にしたり、特定のユーザー向けにページを完全に再設計したりできます。

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

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

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

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

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

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

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

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

多くのオペレーティング システムには、モーションの軽減を指定するためのユーザー補助設定が長い間存在しています。次のスクリーンショットは、macOS Mojave の [モーションを減らす] 設定と Android Pie の [アニメーションを削除] 設定を示しています。これらの設定をオンにすると、オペレーティング システムはアプリ起動アニメーションなどの装飾効果を使用しなくなります。アプリケーション自体もこの設定を尊重し、不要なアニメーションをすべて削除する必要があります。

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

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

Media Queries Level 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 デモアプリの動画

まとめ

最新のウェブサイトでは、ユーザーの設定を尊重することが重要です。ブラウザは、ウェブ デベロッパーがユーザーの設定を尊重できるように、ますます多くの機能を公開しています。たとえば、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 に感謝します。ヒーロー画像: Hannah Cauhepe、Unsplash より。