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

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

誰もが装飾的なアニメーションや遷移を好むわけではありません。また、視差効果のあるスクロールやズーム効果などを見ると、体調不良に陥るユーザーもいます。ユーザー設定のメディアクエリ prefers-reduced-motion を使用すると、そのような設定を行ったユーザーを対象に、モーションを軽減したサイトのバージョンをデザインできます。

対応ブラウザ

  • 74
  • 79
  • 63
  • 10.1

ソース

実生活やウェブでは動きが多すぎる

私は先日、子どもたちとアイススケートをしていました。太陽が輝き、スケート場は人々であふれていました ⛸。唯一の問題は、混雑をうまく処理できないことだけです。あまりに多くのターゲットが動いているため、何も集中できず、迷ってしまいます。アトモリ 🐜? を見つめているような感覚です。

アイススケートをする人たちの足並み。
現実世界での視覚的過多。

ウェブでも同じことが起こりえます。点滅広告、派手な視差効果、意外な出現アニメーション、動画の自動再生など、ウェブはしばしば混乱に陥ることもありますが、幸いなことに、現実にはそういう解決策が存在します。CSS メディアクエリ prefers-reduced-motion を使用すると、モーションの軽減を好むユーザー向けに、ページのバリエーションを作成できます。たとえば、動画の自動再生の禁止から、一部の純粋な装飾的な効果の無効化、特定のユーザー用のページの完全なデザイン変更まで、多岐にわたります。

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

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

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

別のユースケースでは、スケルトン画面、コンテキスト メタデータ、低品質の画像プレビューを組み合わせて、モーションを使用してユーザーの認識をハッキングし、ユーザーの時間の多くを占有し、全体的なエクスペリエンスを高速化します。これは、ユーザーに今後何が起こるかというコンテキストを提供し、その間にできるだけ早く内容を読み込むという考え方です。

最後に、アニメーション グラデーション、視差スクロール、背景動画など、装飾的な効果があります。このようなアニメーションは多くのユーザーにとって好ましいものですが、気を散らしたり、処理が遅くなったりするため、好まれないユーザーもいます。最悪の場合、ユーザーはまるで現実にあった体験であるかのように乗り物に病に苦しむことさえあります。そのため、そのようなユーザーにとっては、アニメーションを減らすことは医療上の必須事項です。

体動による前庭スペクトル障害

アニメーション コンテンツで気が散る、吐き気を感じるユーザーもいます。たとえば、スクロール アニメーションでは、スクロールに関連するメイン要素以外の要素が多く移動すると、前庭障害が発生することがあります。たとえば、視差効果のあるスクロール アニメーションでは、背景要素が前景要素と異なる速度で移動するため、前庭障害を引き起こす可能性があります。前庭(内耳)障害の反応には、めまい、吐き気、片頭痛などがあり、回復にはベッドでの休息が必要になることもあります。

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

多くのオペレーティング システムには、長い間、モーションの抑制を優先するように指定するユーザー補助設定がありました。以下のスクリーンショットは、macOS Mojave の [Reduce motion] 設定と Android Pie の [RemoveAnimation] 設定を示しています。この設定をオンにすると、オペレーティング システムはアプリの起動アニメーションなどの装飾効果を使用しなくなります。アプリ自体もこの設定を尊重し、不要なアニメーションをすべて削除する必要があります。

[モーションを低減] チェックボックスがオンになっている 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> コンテキストからのメディアクエリの操作

興味深いユースケースとして、media 属性に依存してアニメーション AVIF、WebP、GIF を再生することがあります。(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 を実装した Stephen McGruer、および Rob Dodson とともにこの記事をレビューしてくださった Stephen McGruer に感謝します。ヒーロー画像(Hannah Cauhepe 氏、Unsplash より)。