opacity: 0 が引き起こす LCP 判定不能問題
はじめに
PageSpeed Insights を実行したところ、スコアが表示されず、LCP / CLS / TBT などすべての指標がエラー表示になる状況に遭遇しました。サーバ設定や JavaScript、Google Fonts、GTM などを調査した結果、最終的な原因は CSS の opacity: 0 でした。
なぜ opacity: 0 が PageSpeed Insights の計測を妨げるのか、そして実務でどう修正すべきかを整理します。
問題の症状
PageSpeed Insights での表示
- すべての指標が「Error!」表示になる
- LCP(Largest Contentful Paint)が取得できない
- スコアが計測不能
実際のブラウザでの表示
一方で、実ブラウザでは次のように見えます。
- 表示は正常
- ファーストビューも問題なく表示される
- フェードイン演出も意図通り動作する
このように「PSI では失敗するのに、見た目は正常」という乖離があるため、原因の特定が難しくなります。
原因:LCP 要素が opacity: 0 になっていた
結論から言うと、Largest Contentful Paint(LCP)の要素が初期描画時に opacity: 0 だったことが原因です。
LCP の判定ルール
LCP は「ユーザーに実際に表示されている最大要素」を計測します。そのため、以下の状態の要素は LCP から除外されます。
opacity: 0visibility: hiddendisplay: none- その他、視覚的に不可視な状態
初期描画時に LCP 要素が不可視だと LCP が確定できず、結果として スコア算出ができない(多くの指標が「—」や Error になる) ことがあります。
よくある実装パターン(アンチパターン)
.hero {
opacity: 0;
transition: opacity 0.8s ease;
}
.hero.is-visible {
opacity: 1;
}
window.addEventListener('load', () => {
document.querySelector('.hero').classList.add('is-visible');
});
人間の目では問題ない理由
loadイベント後すぐにフェードインする- 体感では最初から表示されているように見える
PageSpeed Insights / Lighthouse での挙動
- 初期描画時点で「表示されていない」と判断される
- LCP が確定できず、
NO_LCP扱いになる - スコア計算ができず、指標が Error / 「—」表示になる
結果として、環境によってはPageSpeed Insights の指標がすべてエラー表示になることがあります。
実際に発生したケース
当サイトで実際に発生し、再現性が確認できた事例です。
修正前のコード
.hero {
opacity: 0;
transition: opacity 0.8s ease;
}
PageSpeed Insights の結果:
- First Contentful Paint:Error!
- Largest Contentful Paint:Error!
- すべての指標が計測不能
試した修正①:opacity を 0.01 にする
.hero {
opacity: 0.01;
transition: opacity 0.8s ease;
}
結果:すべての指標が正常に計測されるようになりました。
この結果から、opacity: 0(完全なゼロ)が「不可視」判定の閾値になっている可能性が高いと分かりました。0.01 であれば視覚的にはほぼ透明でも技術的には「可視」扱いとなり、LCP として認識されます。
推奨される最終的な修正
.hero {
opacity: 1; /* アニメーションは削除 */
}
opacity: 0.01 で計測エラーは回避できましたが、これはあくまで回避策です。ファーストビューやメインビジュアルなど、LCP になり得る要素は初期表示で必ず可視にすることが重要です。
解決方法
基本:LCP 要素では opacity: 0 を使わない
最も確実な方法です。
.hero {
opacity: 1; /* 初期表示は必ず可視 */
}
ファーストビューやメインビジュアル、h1 など、LCP になり得る要素は初期表示で可視にします。
代替案:どうしてもアニメーションが必要な場合
視覚的な演出が必須の場合は、初期値を 0.01 にします。
.hero {
opacity: 0.01; /* 視覚的にはほぼ不可視だが、LCP 判定は通過 */
transition: opacity 0.8s ease;
}
注意: これは回避策です。可能であれば、LCP になり得る要素は初期表示で opacity: 1 にしてください。
ファーストビュー外でのみアニメーションを使う
/* ファーストビューではアニメーションを使わない */
.hero {
opacity: 1;
}
/* スクロール後に表示される要素のみアニメーション */
.section:not(:first-child) .content {
opacity: 0;
transition: opacity 0.8s ease;
}
.section:not(:first-child) .content.is-visible {
opacity: 1;
}
確認方法
Chrome DevTools での確認(推奨)
- DevTools を開く(F12)
- Lighthouse タブを選択
- Mobile を選択
- Analyze page load(または同等の実行ボタン)を実行
- LCP の数値が表示されるか確認
LCP が「Error!」または「—」表示の場合、LCP 要素が正しく認識されていません。
Performance パネルで LCP 要素を特定
- DevTools → Performance タブを開く
- リロードして記録する
- Timings セクションで「LCP」を確認する
- クリックして該当要素がハイライト表示されるか確認する
この方法で、どの要素が LCP として認識されているか(または認識されていないか)を特定できます。
まとめ
- PageSpeed Insights がすべてエラーになる原因は CSS の
opacity: 0 - LCP 要素が不可視だと LCP が確定できず、スコア算出ができない
- サーバや JavaScript が正常でも発生する
- 解決策は LCP 要素を初期表示で可視にすること
opacity: 0.01で回避できる場合はあるが、初期表示で可視にするのが安全
Google Fonts や GTM、サーバ設定を疑ってしまいがちですが、原因は CSS 1 行というケースもあります。同様の症状で悩んでいる場合は、まず opacity や visibility の指定を確認してみてください。