動きとアニメーション

派手なアニメーションは魅力的だが、前庭障害のある人は気分が悪くなり、 光感受性てんかんのある人は発作のリスクが上がる。動きは「オフにできる」のが基本。

動きが引き起こす実害

prefers-reduced-motion メディアクエリ

OS 設定で「視差効果を減らす」を ON にしている人を検出できる。 派手な動きは原則これに従って弱める or 止める

/* 通常時の派手なアニメ */
.hero {
  animation: float 3s ease-in-out infinite;
}

/* reduce 時は止める */
@media (prefers-reduced-motion: reduce) {
  .hero {
    animation: none;
  }
}

「全てのアニメをまとめて止める」セーフティネット

個別に書くのが面倒なときは、ベースとしてすべてのアニメと transition を最低限に:

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

重要なフィードバック(state 切り替え時のフェード等)は完全に消すと UX が悪くなる場合があるので、 個別に最低限残す方が親切。

JS から検出する

const reduce = window.matchMedia("(prefers-reduced-motion: reduce)")

if (reduce.matches) {
  // 派手なアニメをスキップ
}

// 変更を監視
reduce.addEventListener("change", (e) => {
  if (e.matches) stopAllAnimations()
})

GSAP、Framer Motion、React Spring など主要なアニメライブラリは prefers-reduced-motion を読む組み込みオプションを持っている。

パララックススクロール

前庭障害の人にとって最も困るのがパララックス。背景と前景が違う速度でスクロールするため、 三半規管が混乱する。

autoplay 動画・GIF

<video autoplay muted loop playsinline controls>
  <source src="hero.mp4" type="video/mp4" />
</video>

または ユーザーが「再生」ボタンを押すまで動かないのが安全。

点滅と発作リスク

WCAG 2.3.1(必須): 1秒間に3回以上の点滅は禁止。 ただし「全画面の中の小さな部分」かつ「赤の閾値以下」なら許容(細かい数式あり)。 実務上は「点滅は使わない」が一番安全

WCAG 2.3.2(AAA): 1秒3回以上の点滅は面積に関わらず禁止。

スクロールジャック

スクロール量を独自に解釈して画面に表示する量を変える「スクロールジャック」は、 マウスホイール / トラックパッドの感覚を奪うので避ける。

scroll-snap など標準の挙動を使う方が a11y にも親切。

ホバーのみで現れる UI

WCAG 1.4.13(Content on Hover or Focus)。ホバー/フォーカスで現れる吹き出しやドロップダウンは:

ツールチップが「カーソルを動かしたら一瞬で消える」だと、視覚以外でも触覚的にも難しい。

カルーセル / スライドショー

自動回転するカルーセルは注意を奪う + 操作不能の二重苦。

近年は「そもそも自動カルーセルを使わない」ベストプラクティスが主流。

スピナー・ローディングインジケータ

無限ループするスピナー自体は問題ない(小さくゆっくり動くものなら)。気を付けるべきは:

<div role="status" aria-live="polite">
  <span class="sr-only">読み込み中...</span>
  <svg aria-hidden="true" class="spinner">...</svg>
</div>

3D / WebGL シーン

R3FThree.js で作る 3D シーンも例外ではない。

// Three.js
const reduce = matchMedia("(prefers-reduced-motion: reduce)").matches
controls.autoRotate = !reduce

View Transitions と動きの配慮

View Transitions もデフォルトでクロスフェードが入る。 派手なカスタムアニメを当てる時は prefers-reduced-motion 対応を忘れずに。

@media (prefers-reduced-motion: reduce) {
  ::view-transition-group(*),
  ::view-transition-old(*),
  ::view-transition-new(*) {
    animation: none !important;
  }
}

判断ガイド

動き常時OKreduce時に弱める常に避ける
0.2 秒のフェード
軽いスケール変化
大きなスライドイン
パララックス○(off)
ぐるぐる回るループ○(off)
1秒3回以上の点滅
スクロールジャック○(off)
強いストロボ・カメラフラッシュ
設計時に決めておく

サービスの「動きトークン」(duration / easing / 動かす距離)を最初に定めて、reduce 時の代替も同時に決めておく。 実装時に都度判断するのではなく、デザインシステムレベルで保証する。