Anti-FOUC
FOUC(Flash of Unstyled Content)とは、アニメーションが実行される前に要素が最終状態で一瞬表示される現象です。data-animは他のライブラリにはない3層の防御システムでこれを解決します。
FOUCとは?
ページが読み込まれると、HTMLのレンダリングとJavaScriptの実行の間に短い隙間があります。この間、アニメーション対象の要素は最終位置で表示され、アニメーションライブラリが初期化されると開始位置に「ジャンプ」します。
従来のライブラリ(AOSなど):
ページ読み込み → 要素が最終位置で表示 → JS読み込み → 要素が開始位置にジャンプ → アニメーション
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
これがFOUC
data-anim:
ページ読み込み → 要素はCSSで非表示 → JS準備完了 → スムーズにアニメーション
^^^^^^^^^^^^^^^^^^^^^^
フラッシュもジャンプもなし
3層の防御
第1層:同期スクリプト
data-animは<head>内で同期的な<script>タグとして読み込まれます。asyncやdeferではありません。これにより、ブラウザがコンテンツをレンダリングする前にCSSが注入されます。
<!-- Correct: synchronous in <head> -->
<head>
<script src="https://unpkg.com/data-anim@latest/dist/data-anim.js"></script>
</head>
<!-- Wrong: async/defer causes FOUC -->
<head>
<script async src="data-anim.js"></script>
</head> 第2層:インラインクリティカルCSS
スクリプトは即座にすべての[data-anim]要素を非表示にする小さなCSSルールを注入します:
[data-anim] { opacity: 0; }
これはブラウザの最初のペイント前に実行されるため、要素がアニメーション前の状態で表示されることはありません。
第3層:アニメーションキーフレーム
各アニメーションのキーフレームは非表示状態(opacity: 0、変形位置)から始まり、最終状態にアニメーションします。アニメーションがトリガーされると、要素は非表示から表示へスムーズに遷移します。
タイミング図
Browser Timeline:
─────────────────────────────────────────────────────>
1. HTMLパースの開始
2. <head>内の<script>を検出
├─ CSS注入: [data-anim] { opacity: 0 } ← 第2層
└─ IntersectionObserverのセットアップ
3. 最初のペイント - data-anim要素は非表示 ← FOUCなし!
4. 要素がビューポートに入る
5. アニメーション再生: opacity 0 → 1 + transform ← 第3層
なぜ同期スクリプトか?
他のライブラリはページレンダリングのブロックを避けるためにasyncやdeferを使用します。しかし、これによりライブラリが要素を非表示にする前にページがペイントされるレースコンディションが発生します。
data-animのスクリプトは非常に小さく(2KB未満)、ブロック時間はごくわずかで、通常5ms未満です。これは意図的なトレードオフです:5msのブロック時間ですべてのFOUCを排除します。
他のライブラリとの比較
| Feature | data-anim | AOS | Animate.css | GSAP |
|---|---|---|---|---|
| Anti-FOUCビルトイン | ✅ | ❌ | ❌ | ❌ |
| 読み込み時のフラッシュなし | ✅ | ❌ | ❌ | ❌ |
| JSフォールバックなしで動作 | ✅ | ❌ | ✅ | ❌ |
| 設定不要のAnti-FOUC | ✅ | ❌ | ❌ | ❌ |
data-animはこれらすべてを自動的に処理します。追加のCSSは不要。