<img> 基础与防抖
基于 HTML Living Standard · 核于 2026-06
速查
<img>是空元素(无闭合标签),最少需要src(或srcset)+altalt写「图传达的信息 / 作用」而非「图长什么样」;别写「一张图片 / 截图」之类废话- 装饰图用
alt=""(空值,读屏跳过);缺了alt属性反而会让读屏念文件名 width/height:整数、无单位(CSS 像素),写上就让浏览器算出宽高比、预留空间,防 CLS 抖动- 现代 CSS 下即使宽度被改写,
width/height仍提供宽高比(配合height: auto) loading="lazy":首屏外的图延迟到接近视口再下载(Baseline 广泛可用);首屏主图保持默认eagerdecoding="async":异步解码、不阻塞渲染;sync/auto(默认)按需选fetchpriority="high":抬高首屏 LCP 主图的下载优先级(新近可用,老浏览器忽略)- 懒加载只在启用 JS 时生效(反追踪设计);懒加载图务必写死
width/height,否则未加载时是 0×0
<img> 的最小写法
<img> 是个空元素(void element),没有闭合标签,把图片以「替换内容」的形式塞进文档流。它最少需要两个属性:
<img src="cat.jpg" alt="一只橘猫趴在键盘上睡觉" />src:图片地址(URL),必填——浏览器据此发请求、下载、渲染;alt:替代文字,必写——读屏软件朗读它、图加载失败时显示它、搜索引擎据它理解图意。
src 与 srcset 至少有一个
严格说,<img> 要求 src 与 srcset 至少存在一个。日常都写 src(也是不支持 srcset 的旧浏览器的兜底);srcset 是在它之上做响应式的增强,详见 响应式图片。
alt:写「信息」不写「长相」
alt 是无障碍的核心,但最容易写错。原则只有一条:写这张图想传达的信息或承担的作用,而不是描述它的外观。
| 场景 | ❌ 别这么写 | ✅ 应该写 |
|---|---|---|
| 放大镜图标(搜索按钮) | alt="放大镜图片" | alt="搜索" |
| 折线图 | alt="一张折线图" | alt="2020–2025 销售额逐年增长,2025 达 1.2 亿" |
| 文章配图 | alt="图片" | alt="工程师在白板上画系统架构" |
| 纯装饰分隔线 | alt="装饰线条" | alt=""(空值,让读屏跳过) |
几个要点:
- 别写「一张图片 / 截图 / 照片」:
<img>元素本身已经告诉读屏「这是图」,再念一遍是噪音; - 图标按含义写:放大镜写
alt="搜索"、齿轮写alt="设置",而不是描述形状; - 图表 / 截图写结论:传达「从图里能看出什么」,而不是「图里有几根线」。
装饰图:alt="" 而非省略
<!-- ✅ 装饰图:空 alt,读屏直接跳过 -->
<img src="divider.svg" alt="" />
<!-- ❌ 省略 alt:部分读屏会去念文件名 "divider.svg" -->
<img src="divider.svg" />空 alt="" 与「没有 alt 属性」是两回事:前者明确告诉读屏「这图无信息,跳过」,后者会让某些读屏退而念出文件名或 URL。纯装饰、背景性质的图,更好的做法其实是用 CSS background-image 而非 HTML <img>——内容图才进 HTML。
width / height:一行属性消灭布局抖动
这是性能上最划算的一笔投资。给 <img> 写上 width 和 height:
<img src="hero.jpg" alt="产品主视觉" width="1200" height="630" />注意值是整数、不带单位(代表图片的固有像素尺寸),不是 1200px。它的作用是:浏览器在图片还没下载完时,就能据 width / height 算出宽高比,提前把对应大小的空白格子占住。等图片到位,直接填进格子,不会把下方内容往下挤——这就避免了「累积布局偏移」(Cumulative Layout Shift,CLS)。
不写尺寸会怎样
不写 width / height 时,浏览器在图片下载完之前不知道它多大,只能先按 0 高度排版;图一到,猛地撑开高度,把下方文字、按钮整体往下顶——用户正要点的按钮瞬间跑位。CLS 是 Core Web Vitals 的三大指标之一,图片漏写尺寸是它最常见的成因。
现代 CSS 里你通常会用 max-width: 100% 让图自适应容器宽度。好消息是:即便 CSS 改写了显示宽度,HTML 的 width / height 依然向浏览器提供宽高比,配合下面这条经典 CSS 就能既响应式又不抖动:
img {
height: auto; /* 高度按宽高比自动算,避免变形 */
max-width: 100%; /* 不超出容器 */
}loading:原生懒加载
loading 控制图片何时开始下载:
<img src="below-fold.jpg" alt="页面下方的配图" width="800" height="450"
loading="lazy" />| 取值 | 行为 |
|---|---|
eager | 立即下载,不管在不在视口(默认) |
lazy | 延迟到图片接近视口时再下载,省流量、快首屏 |
实战准则:
- 首屏外的图用
lazy:文章中段插图、列表里靠下的卡片,能显著减少首屏请求; - 首屏主图别用
lazy:它往往就是 LCP(最大内容绘制)元素,懒加载反而拖慢首屏,保持默认eager; - 懒加载图必须写死
width/height:未加载时图是 0×0,没尺寸会引发更严重的抖动。
懒加载与 JS 的关系
原生懒加载只在启用 JavaScript 时生效——这是一项反追踪设计:若禁用脚本仍懒加载,站点就能靠 iframe / 图片的请求时机反推用户滚动位置。另外,视口内的懒加载图在 load 事件触发时可能尚未加载完,别在 load 里假设所有图都就绪。
decoding 与 fetchpriority:两个微优化
<img src="hero.jpg" alt="主视觉" width="1200" height="630"
fetchpriority="high" decoding="async" />decoding 提示浏览器如何安排图片解码:
| 取值 | 含义 |
|---|---|
sync | 与其余 DOM 同步解码,一起呈现 |
async | 异步解码,先渲染其余内容、稍后呈现图片 |
auto | 不表态,由浏览器决定(默认) |
对静态 <img> 几乎感知不到差别;当你用 JS 动态插入大图时,async 能避免解码阻塞主线程造成的卡顿。
fetchpriority 调整下载优先级(high / low / auto,默认 auto)。最典型用法是给首屏 LCP 主图加 fetchpriority="high",让它在一堆图片里优先下载。它是新近可用的能力,老浏览器忽略,属于「锦上添花」。
一份带注释的「完整 <img>」
<img
src="photo-800.jpg"
srcset="photo-480.jpg 480w, photo-800.jpg 800w, photo-1200.jpg 1200w"
sizes="(max-width: 600px) 100vw, 50vw"
alt="工程师在白板上画系统架构"
width="1200"
height="800"
loading="lazy"
decoding="async" />这里 src 兜底、srcset / sizes 做响应式、width / height 防抖、loading / decoding 做性能——日常一张「认真写」的图片基本就是这套。其中 srcset / sizes 的挑图逻辑,是下一页的主题。
小结
alt 决定「无障碍与失败回退」,width / height 决定「不抖动」,loading / decoding / fetchpriority 决定「多快、按什么顺序加载」。把这四件事做对,单张图片就已经「正确且高性能」。但当一张图要适配从手机到 4K 的各种屏幕时,光靠 src 不够——下一页进入 响应式图片。