一张未压缩的 4000px 照片丢进 <img>,手机也得下载那张原图。布局还没出来,宽度高度不知道,整页会先跳一下。图片问题多半不是「要不要用 WebP」,而是尺寸没告诉浏览器。
先占住位置
html
<img
src="/covers/html-page-skeleton-800.jpg"
width="1200"
height="750"
alt="编辑器里的 HTML 骨架"
/>width / height 给的是固有比,浏览器能算出 aspect-ratio,图片到来之前不会把下面的标题顶下去。CSS 里再写:
css
img {
max-width: 100%;
height: auto;
}让设备自己挑文件
html
<img
src="/covers/post-800.jpg"
srcset="
/covers/post-480.jpg 480w,
/covers/post-800.jpg 800w,
/covers/post-1200.jpg 1200w
"
sizes="(max-width: 700px) 100vw, 720px"
alt=""
/>srcset 是候选文件,sizes 是「这张图在页面上大概多宽」。没有 sizes,浏览器会按整屏宽度去挑,小图栏位也会下 1200px。
封面图如果只在卡片右侧出现,sizes 写 160px 一类的固定值,比 (max-width: 700px) 100vw 更准。
首屏以外再懒加载
html
<img src="/photos/02.jpg" alt="" loading="lazy" decoding="async" />首屏大图不要 lazy,否则它会等布局算完才开始下,LCP 反而变差。下面的列表、评论区头像可以懒加载。
一张检查清单
- 导出时就缩到实际显示宽度的 2 倍(视网膜),不要丢 4K 原片
- 永远带
widthheight或aspect-ratio - 超过一种宽度就写
srcset+sizes - 装饰图
alt="",有信息的图写一句人话,不要写「图片」
Next.js 的 next/image 会帮你做一部分,但 sizes 仍要你按栏宽填。填错的话,它一样会下过大的图。
