見出し画像

🗣prefers-reduced-motionメディアクエリでアニメーション酔いに配慮する

たかもそ/Web Creator.

近年、CSS や JavaScript の進化により、パララックスやスクロールとともにアニメーションしながら登場するエフェクトなど、演出のためのアニメーションがかなり増えました。

Web サイトに独自性を出すことができて重宝される一方で、過度なアニメーションによる画面酔いを訴える人も出てきています。

そこで、CSS Media Queries Level 5 では、prefers-reduced-motion 特性が提案されています。

過度なアニメーションとは

アニメーションには本来、ロード画面やスケルトンスクリーンなど、ユーザーに現在の進行状況を伝えるという大事な役目があります。

ここでいう過度なアニメーションとは、背景のアニメーションや画面全体に広がる背景動画、パララックスエフェクト、画面遷移などの本質的でないアニメーションのことです。

パララックスエフェクトのように、背面と前面でスクロールのスピードが違うことで、画面酔いを起こす場合があります。

あくまで、prefers-reduced-motion であって prefers-no-motion ではないため、すべてのアニメーションをなくすわけではありません。

デバイスの設定

しかし、prefers-reduced-motion 特性が実装されたことで、すべて解決というわけにはいかないようです。

デバイスのどの設定項目によって prefers-reduced-motion 特性が判定されるかをしっかり理解しておく必要があります。これは、開発者だけでなく、実際に使うユーザーも認識しておいた方がよいと思います。

Windows の設定

Windows には、prefers-reduced-motion 特性に関する設定が複数箇所に存在します。

まず  1 つ目は、[設定] > [簡単操作] > [ディスプレイ] > [Windows にアニメーションを表示する] のトグルです。

画像1

2 つ目は、[コントロールパネル] > [システムとセキュリティ] > [システム] > [システムの詳細設定] > [パフォーマンス設定] > [視覚効果] にある [Windows 内のアニメーションコントロールと要素] というチェックボックスです。

画像2

そして 3 つ目は、[コントロールパネル] > [コンピューターの簡単操作] > [コンピューターの簡単操作センター] > [コンピューターを見やすくします] にある [必要のないアニメーションは無効にします(可能な場合)] というチェックボックスです。

画像3

ここで注意したいのが、3 つの設定のうち 2 つ目のパフォーマンス設定に関してはアクセシビリティの設定ではなく、単に Windows の動作を軽くするために余分なアニメーションを無効にしたい人が設定するものだということです。

すると、Windows 側のアニメーションだけを無効にするつもりが、ブラウザ上のアニメーションまで無効にされてしまうという問題が起きます。

Windows 側のアニメーションは無効にしつつ、ブラウザ上のアニメーションは有効にしたい場合は、[Windows 内のアニメーションコントロールと要素] チェックボックスはチェックを入れたまま、その他の項目を個別にオフにしていく必要があります。

現在の状況では、アクセシビリティとパフォーマンスの2つの観点からアニメーションの制御を行うことができるため、混乱を招く恐れがあると思われます。

MacOS の設定

[システム環境設定] > [アクセシビリティ] > [ディスプレイ] > [視差効果を減らす] というチェックボックスで設定します。

画像4

iOS の設定

[設定] > [アクセシビリティ] > [動作] > [視差効果を減らす] というトグルで設定します。

画像5

Android の設定

[設定] > [ユーザー補助] > [視認性向上] > [アニメーションを削除] というトグルで設定します。

画像6

このように、各デバイスで設定できるようになっています。

メディアクエリの書き方

さて、どの設定が prefers-reduced-motion 特性に影響を及ぼすか理解したところで、実際にメディアクエリを書いてみます。

視差効果を減らすように設定されているときに transition や animation を無効にすればよいので、以下のようになります。

@media (prefers-reduced-motion: reduce) {
  *,
  ::before,
  ::after {
    transition: none !important;
    animation: none !important;
  }
}

しかし、この書き方には 2 つの問題点があります。

たとえば、opacity プロパティの値が 0 から 1 に変わるアニメーションの場合、animation: none !important; としてしまうと、要素がずっと表示されないままになってしまいます。

そしてもう 1 つ、transitionend や animationend イベントが発火しない問題が発生します。アニメーションが終了したときに JavaScript で何らかの処理を行う場合、イベントが発火しないため処理が行われないままとなってしまいます。

そこで、次のように指定します。

@media (prefers-reduced-motion: reduce) {
  *,
  ::before,
  ::after {
    animation-delay: -1ms !important;
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
    transition-delay: 0s !important;
    transition-duration: 1ms !important;
  }
}

animation-duration プロパティに 1ms という非常に短い時間を指定することで、アニメーションは実行されるため問題点は解消されます。

animation-delay プロパティに -1ms を指定しているのは、負の値を指定することで 1ms 後の状況からアニメーションが開始され、実質アニメーションの描画をなくすためです。

また、animation-iteration-count プロパティに 1 を指定することで、無限に再生される infinite アニメーションが 1 度だけ再生されるようにします。

transition プロパティも animation と同様に指定しますが、transition-delay プロパティに -1ms を指定すると Chrome で transitionend イベントが発火しないという問題があるため、0s としています。

transition-duration プロパティに 0s を指定している例も見かけますが、Safari で transitionend イベントが発火しなくなるので、1ms としています。

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

ついでに、background-attachment と scroll-behavior プロパティも無効にしておくといいかもしれませんね。

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

また、一部の要素にのみ指定したいときは :not(.safe-animation) というようにすれば、.safe-animation クラスが指定されている要素は除外できます。

対応ブラウザ
・IE -
・Edge -
・Chromium Edge 79
・Firefox 63
・Chrome 74
・Safari 10.1
・Opera 62
・iOS Safari 10.3
・Android 79

すでに、ほぼすべてのブラウザが対応しているので、今から対応していくとよいと思います。

今すぐ始めるCSSレシピブック

この記事が気に入ったら、サポートをしてみませんか?
気軽にクリエイターの支援と、記事のオススメができます!