ひとことで言うと
CLS(Cumulative Layout Shift)はページが表示されている間に発生したすべてのレイアウトシフトの累積スコアです。Googleは0.1以下を「良好」として定義しており、0.25以上は「改善が必要」です。値が高いほど「読もうとしていた文章が急に下に押し下げられた」「ボタンを押そうとしたら別のボタンに変わった」という体験が多い状態を意味します。
AI生成HTMLでCLSが発生する主な原因は、画像タグにwidthとheightを指定していない・Webフォントが遅れて読み込まれてテキスト行数が変わる・遅延読み込みしたコンテンツが後から挿入されるの3パターンです。これらを共有前に確認するだけでCLSを大幅に改善できます。
- 相手がログインなしで開ける状態か確認する
- PCとスマホで最低1回ずつ表示を確認する
- 内部情報・個人情報・不要な外部送信が残っていないか見る
- レビュー期限と修正時の差し替え方を決めておく
HTML共有で関係する場面
プレゼン用のHTML資料を共有したとき、受け取った相手が画像の読み込み中にテキストを読もうとしたら画像が挿入されて文章の位置がずれることがあります。これはimgタグにwidth・height属性がないために発生します。`<img src="photo.webp" width="800" height="600">`のようにサイズを明示すると、ブラウザが事前にスペースを確保してレイアウトシフトを防げます。
ギガサイト便でURLに変換したHTMLを受け取った相手がスマートフォンで縦スクロールしながら読む際、フォントが途中で切り替わってテキストの行高が変わり、以降のコンテンツが全体的にずれるケースがあります。`font-display: swap`の設定に加えてCSSで`line-height`を固定値で指定すると、フォント切り替え時のずれを最小限に抑えられます。
よくある誤解
「CLSはアニメーションで発生する」という誤解があります。CSSのtransitionやanimationでユーザー操作に応じて要素が動く場合はCLSにカウントされません。CLSが記録されるのは「ユーザーが操作していないのに勝手に動いた」レイアウト変化のみです。スムーズなスクロールアニメーションや、ボタンを押したときの展開はCLSに影響しません。
「画像サイズを指定すれば完全にCLSがなくなる」も過信は禁物です。動的に挿入される広告バナーやEmbed系のウィジェット(SNS投稿の埋め込みなど)はサイズが確定してから挿入されることがあり、imgのサイズ指定とは別にコンテナのmin-heightを設定する必要があります。
安全に使うための注意点
CLSを改善するためにすべての画像に固定サイズを指定する際、モバイル表示でも同じサイズになってしまわないよう注意が必要です。`width="100%" height="auto"`と記述するとアスペクト比を保ちながらレスポンシブに動作します。CSSのaspect-ratioプロパティを組み合わせると、レスポンシブながらブラウザがスペースを事前確保できる理想的な設定になります。
CLSの測定はLighthouseの静的計測だけでは不十分なことがあります。Webフォントや外部サービスの読み込みタイミングは計測のたびに変わるため、ChromeのDevTools→Performanceタブで実際に録画して「Layout Shift」マーカーを目視で確認することが確実です。修正後も複数回計測して安定していることを確かめましょう。
よくある質問
AI生成HTMLのCLSスコアが0.3で改善したいのですが、まず何を確認すればいいですか?
ChromeのDevToolsでPerformanceを録画してLayout Shiftが発生した瞬間の要素を特定してください。多くの場合は画像のwidthとheight属性の欠如かWebフォントの遅延切り替えが原因で、それぞれimgの属性追加とfont-display設定で対処できます。
imgタグにwidthとheightを指定するとスマートフォンで表示が崩れる心配があります。どう対処しますか?
imgタグのwidth・heightはアスペクト比の情報としてブラウザが使い、CSSのmax-width:100%とheight:autoでリサイズが効きます。HTML属性でサイズ指定しつつCSSで`img { max-width: 100%; height: auto; }`を設定すれば、レスポンシブ表示を維持したままCLSを防げます。
CLSの原因がGoogleマップの埋め込みiframeだとわかりました。対処方法はありますか?
iframeを囲むdivにCSSで`aspect-ratio: 16/9; min-height: 300px`などを設定してスペースを事前確保します。iframeにheight属性を直接付けても効果があります。コンテナのサイズが確定していればmapの読み込み前後でレイアウトが動かなくなります。