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

まとめ

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