― 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(完全なゼロ)が「不可視」判定の閾値になっている可能性が高いと分かりました。視覚的にはほぼ不可視でも、技術的には「可視」扱いとなり、LCP として認識されます。
推奨される最終的な修正
.hero {
opacity: 1; /* アニメーションは削除 */
}
opacity: 0.01 で解決することは確認できましたが、これは回避策です。ファーストビューやメインビジュアルなど、LCP になり得る要素は、初期表示で必ず可視にすることが重要です。
解決方法
基本:LCP 要素では opacity: 0 を使わない
最も確実な方法です。
.hero {
opacity: 1; /* 初期表示は必ず可視 */
}
ファーストビューやメインビジュアル、h1 など、LCP になり得る要素は必ず初期表示で可視にすることが重要です。
代替案:どうしてもアニメーションが必要な場合
視覚的な演出が必須の場合:
.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 の指定を確認してみてください。