现场是这样的。首屏大图外面套了一层半透明遮罩,LCP 候选元素变成了遮罩 div,预加载扫描器找不到真实的图片地址,图要等 CSS 解析完才开始下载。
中间走过弯路,把「预加载只认 img 与 link,背景图不在扫描范围」当成主因,改完现象没变。
真正麻烦的地方在于,几个原因的现象几乎一样。LCP 元素被绝对定位的遮罩覆盖,浏览器把遮罩当成了最大绘制块;图片写在 CSS 的 background-image 里,HTML 里没有 img 标签;图片地址带 hash 参数,每次发版都变成新 URL。
动手时先确认首屏最大绘制元素
curl -s https://www.example.com/ | findstr /i "hero-mask"
然后看背景图是怎么写的
curl -s https://www.example.com/css/main.css | findstr /i background-image
随后把首图改成 img 并保留遮罩层
echo '<img class="hero-img" src="/img/hero.jpg" width="1600" height="900" fetchpriority="high">';
末了加 preload 让扫描器提前发现
echo '<link rel="preload" as="image" href="/img/hero.jpg" fetchpriority="high">';
中间停过一次,把已经改的东西回滚干净,再重新来一遍。
怎么算真的好了,看的是同一批现象。首图改成 img 并加 preload 后,下载提前了 600ms,LCP 从 3.6 秒降到 2.4 秒。
遮罩层会抢走 LCP 的身份,首屏主图尽量用 img 标签,至少让预加载扫描器能看见它。如果同一现象隔几天又出现,说明根因没找到,别当偶发处理。
