meguro.css 第8回 LTメモ

meguro.cssでLTした時の話の雑まとめです。
怪文書になっていて、後から画像とかリンクが追加されていく予定です

TL;DR

  1. CSSアニメーションは変なのに依存しないから楽
  2. prefers-reduced-motion 色々とつらい
  3. CSSのプライバシー懸念事項

変なのに依存しないのがいい

requestAnimationFrameのようなフレームベースのアニメーションは、new Date()performance.now()という胡散臭い何かに依存するが、CSS Transition / Animation / WAAPI のアニメーションは、その辺Pureでよさそう、という話をしました。
requestAniamtionFrameはcallbackにperformance.now()を渡しているだけで、そのcallback自体はPureでは?と思ってしまうのですが、ブラウザ側で思わぬ副作用があるというニュアンス。

date-fnsで、Pureじゃなさそうな処理があったことと、react-springのこのバグが元ネタです。

CSS Transition / Animationは宣言的で、終着点が決まっています。
また、専用のアニメーションエンジンで動きます(これはWAAPIも含む)。Animation Inspectorなどで挙動をデバッグできます。

一方、requestAnimationFrameなどの動作は、タイムスタンプを計測する特性上、リフレッシュレートや時間に強く依存した処理になります。
new Date()Performance.now()は、時間精度がFingerprintingの対象となるため、ブラウザがFingerprintingを抑制する場合に、予期しない動作を引き起こすかも?という話をしました。

privacy.resistFingerprintingという設定がFirefoxの「高度な設定」にあります。
この設定はTor Browserから移植されたもので、Tor Brower同等の機能やバグを持つようです。

このprivacy.resistFingerprintingが時間の精度を下げ、performance.now()などで計測できる数値が100ms〜になります。これはアニメーションが理想としている〜16.7msを超えているので、めっちゃカクカクした動きっぽくなる、という話でした。 バグみたいな話ですが、仕様を考えるとこれが正しい挙動をしているように思えます。

jquery.Animate()やTweenMaxなどの主要アニメーションライブラリは、この設定の前には全滅します。
ただ、CSSやWAAPIでは表現できれないものがあったり、CSS Property以外は操作できないから、という話もしました。
LTではWeb Animations Level 2で挙がっているCustom Effectsに触れましたが、これはまだUnofficial Draftです。

メディアクエリで変えられるのがいい話

アニメーションをやめたいケースについても調べました。

Windows, Mac, iOSなどには、画面の視差効果を減らすための設定があります。
すべてのユーザーがアニメーションを望んでいるわけではないし、速度を遅くしてほしい場合があります。

Media Queries Level 5で、prefers-reduced-motion: reduceというメディアクエリが設定できるようになりました。

css
@media (prefers-reduced-motion: reduce) {
  .animationFoo {
    animation-duration: 0.01s !important;
  }
}

Animate.css など、この設定を利用しているライブラリも存在します。

CSSではメディアクエリ一発でラクラクですが、JavaScriptや主要フレームワーク/ライブラリではそれぞれ異なる対応が必要だよ、という話をしました。
そもそもアニメーション云々ではなく、冗長なアニメーションを停止またはスキップできる仕組みがあることが大事な気がしますが、それは話しませんでした。

CSSのプライバシー懸念事項

アクセシビリティの観点で見られがちなprefers-reduced-motionというかMedia Queries Level 5ですが、プライバシーの観点で見るとFingerprintingの危険性をはらんでいます。
OSの設定をWebに反映させたいユーザーの要望を、コンテンツに対して公開しなければいけないためです。
FingerPrintingのネタとしては十分で、JavaScriptならmatchMediaで何かできます。

javascript
if (typeof window !== undefined &&
  window.matchMedia &&
  window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
    // 視差効果を減らす設定がオンの場合の処理
  }

privacy.resistFingerprintingではその挙動も抑制します。

反省

途中からブラウザ側の実装見るのが疲れて深掘りしていないこと