実践Webアクセシビリティ

ウェブサイトのアニメーションをアクセシブルにする:`prefers-reduced-motion`実践ガイド

Tags: アクセシビリティ, CSS, JavaScript, アニメーション, prefers-reduced-motion

はじめに:アニメーションとアクセシビリティ

ウェブサイトにおけるアニメーションやトランジションは、ユーザーインターフェースを豊かにし、注目を集めたり、状態変化を視覚的に伝えたりするのに役立ちます。しかし、人によってはこれらの動きが不快感、集中困難、さらにはめまいや吐き気といった乗り物酔いに似た症状を引き起こす可能性があります。特に、前庭障害を持つユーザーにとって、予期せぬ動きや過度なアニメーションはサイトの利用を困難にする要因となります。

Webアクセシビリティの観点から見ると、すべての人にとって快適で利用可能な体験を提供することが重要です。そのため、ユーザーがアニメーションの量を制御できるようにすることは、アクセシビリティ対応において非常に重要な要素の一つとなります。ここでは、そのための具体的な実装方法として、CSS Media Queryのprefers-reduced-motionに焦点を当てて解説します。

prefers-reduced-motionとは

prefers-reduced-motionは、ユーザーがオペレーティングシステムまたはユーザーエージェント(ブラウザ)の設定で、アニメーションや動きの量を減らすことを希望しているかどうかを検出するためのCSS Media Queryです。

ユーザーは、OSのアクセシビリティ設定(例:Windowsの「アニメーションを表示する」、macOSの「視覚効果を減らす」)でこの設定を有効にできます。ウェブサイトはこの設定を検知し、アニメーションを控えめにしたり、完全に無効にしたりといった対応を行うことで、ユーザーの好みに合わせた表示を提供できます。

このMedia Queryには以下の2つの値があります。

CSSでの基本的な実装方法

prefers-reduced-motion: reduce Media Queryを使用することで、CSSでアニメーションやトランジションを条件付きで制御できます。

たとえば、要素が表示される際にフェードインアニメーションを適用しているとします。

.fade-in {
  opacity: 0;
  transform: translateY(20px);
  animation: fadeIn 0.5s ease-out forwards;
}

@keyframes fadeIn {
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

このアニメーションを、ユーザーが動きを減らす設定にしている場合は無効にするには、以下のようにMedia Queryを使用します。

.fade-in {
  opacity: 0;
  transform: translateY(20px);
  animation: fadeIn 0.5s ease-out forwards;
}

@keyframes fadeIn {
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* ユーザーが動きを減らすことを希望している場合 */
@media (prefers-reduced-motion: reduce) {
  .fade-in {
    /* アニメーションを無効化 */
    animation: none;
    /* 初期状態から最終状態に即座に移行 */
    opacity: 1;
    transform: translateY(0);
  }
}

このように、@media (prefers-reduced-motion: reduce)ブロック内で、対象要素のanimationプロパティやtransitionプロパティをnoneに設定します。また、アニメーションやトランジションなしで要素が期待される最終状態になるように、プロパティの値を直接設定することも重要です(上記の例ではopacity: 1; transform: translateY(0);)。

より広範に、サイト全体の不要な装飾アニメーションやトランジションを一括で無効化する場合、以下のようなスタイルを適用することも考えられます。

@media (prefers-reduced-motion: reduce) {
  /* 全てのアニメーションとトランジションを無効化 */
  * {
    animation: none !important;
    transition: none !important;
  }

  /* スムーズスクロールも無効化することが望ましい場合 */
  html {
    scroll-behavior: auto !important;
  }
}

!importantの使用は通常避けるべきですが、アクセシビリティの強制的な設定として、基になるスタイルを確実に上書きするためにここでは有効な場合があります。ただし、この方法は強力すぎるため、サイトの特性やアニメーションの役割を考慮し、より粒度の細かい制御を検討することを推奨します。例えば、重要なフィードバックを示すようなアニメーション(例:フォーム送信成功時のチェックマークアニメーション)は無効化せず、装飾的なものだけを対象にする方がユーザー体験を損ねません。

JavaScriptでの実装方法

JavaScriptでアニメーションを制御している場合や、CSSだけでは対応が難しい複雑なアニメーション(例:Canvasを使った描画アニメーション、特定のJSライブラリを使ったアニメーション)に対しては、JavaScriptからprefers-reduced-motionの設定状態を取得して処理を分岐させることができます。

これはwindow.matchMedia()メソッドを使用して行います。

const mediaQuery = window.matchMedia('(prefers-reduced-motion: reduce)');

function handleReducedMotionChange(event) {
  if (event.matches) {
    // ユーザーは動きを減らすことを希望している
    console.log('Reduced motion is preferred.');
    // ここでJavaScriptによるアニメーションを停止または簡素化する処理を記述
    disableComplexAnimations();
  } else {
    // ユーザーは特に設定していない、またはアニメーションを減らすことを希望していない
    console.log('Reduced motion is not preferred.');
    // ここで通常のアニメーションを開始または有効化する処理を記述
    enableComplexAnimations();
  }
}

// 初期状態のチェック
handleReducedMotionChange(mediaQuery);

// ユーザー設定の変更をリッスン
mediaQuery.addListener(handleReducedMotionChange);

// 例:アニメーションを制御する関数
function disableComplexAnimations() {
  // 例: Canvasアニメーションを停止
  if (typeof stopCanvasAnimation === 'function') {
    stopCanvasAnimation();
  }
  // 例: 特定の要素のアニメーションクラスを削除
  const animatedElements = document.querySelectorAll('.js-animated');
  animatedElements.forEach(el => {
    el.classList.remove('is-animating');
    // 最終状態に設定するなど
  });
}

function enableComplexAnimations() {
   // 例: Canvasアニメーションを開始
  if (typeof startCanvasAnimation === 'function') {
    startCanvasAnimation();
  }
  // 例: 特定の要素にアニメーションクラスを追加
  const animatedElements = document.querySelectorAll('.js-animated');
  animatedElements.forEach(el => {
    el.classList.add('is-animating');
  });
}

window.matchMedia('(prefers-reduced-motion: reduce)')MediaQueryListオブジェクトを返します。このオブジェクトのmatchesプロパティで現在の設定状態を確認できます。また、addListener()メソッド(新しいAPIではaddEventListener)を使って、ユーザーがOS/ブラウザの設定を変更した際に通知を受け取り、動的にページの表示を更新することも可能です。

実装時の注意点と考慮事項

テスト方法

prefers-reduced-motionの実装をテストするには、開発者ツールを使用する方法と、OSやブラウザのネイティブ設定を変更する方法があります。

これらの方法で、prefers-reduced-motionreduceに設定された状態でサイトがどのように表示され、機能するかを確認してください。

まとめ

prefers-reduced-motion Media Queryを活用することは、Webサイトのアニメーションやトランジションによる潜在的な問題を解消し、より多くのユーザーにとって快適で利用しやすい体験を提供するために不可欠なアクセシビリティ対応です。CSSやJavaScriptでこの設定を検知し、アニメーションを適切に制御することで、ユーザーの健康や快適さを尊重する設計が可能になります。

この記事が、prefers-reduced-motionの実装を始めるための一助となれば幸いです。ユーザーのニーズに寄り添った、柔軟でアクセシブルなWebサイト開発を目指しましょう。