Skip to content

<img> 基础与防抖

基于 HTML Living Standard · 核于 2026-06

速查

  • <img>空元素(无闭合标签),最少需要 src(或 srcset)+ alt
  • alt 写「图传达的信息 / 作用」而非「图长什么样」;别写「一张图片 / 截图」之类废话
  • 装饰图alt=""(空值,读屏跳过);缺了 alt 属性反而会让读屏念文件名
  • width / height:整数、无单位(CSS 像素),写上就让浏览器算出宽高比、预留空间,防 CLS 抖动
  • 现代 CSS 下即使宽度被改写,width / height 仍提供宽高比(配合 height: auto
  • loading="lazy":首屏外的图延迟到接近视口再下载(Baseline 广泛可用);首屏主图保持默认 eager
  • decoding="async":异步解码、不阻塞渲染;sync / auto(默认)按需选
  • fetchpriority="high":抬高首屏 LCP 主图的下载优先级(新近可用,老浏览器忽略)
  • 懒加载只在启用 JS 时生效(反追踪设计);懒加载图务必写死 width / height,否则未加载时是 0×0

<img> 的最小写法

<img> 是个空元素(void element),没有闭合标签,把图片以「替换内容」的形式塞进文档流。它最少需要两个属性:

html
<img src="cat.jpg" alt="一只橘猫趴在键盘上睡觉" />
  • src:图片地址(URL),必填——浏览器据此发请求、下载、渲染;
  • alt:替代文字,必写——读屏软件朗读它、图加载失败时显示它、搜索引擎据它理解图意。

srcsrcset 至少有一个

严格说,<img> 要求 srcsrcset 至少存在一个。日常都写 src(也是不支持 srcset 的旧浏览器的兜底);srcset 是在它之上做响应式的增强,详见 响应式图片

alt:写「信息」不写「长相」

alt 是无障碍的核心,但最容易写错。原则只有一条:写这张图想传达的信息或承担的作用,而不是描述它的外观

场景❌ 别这么写✅ 应该写
放大镜图标(搜索按钮)alt="放大镜图片"alt="搜索"
折线图alt="一张折线图"alt="2020–2025 销售额逐年增长,2025 达 1.2 亿"
文章配图alt="图片"alt="工程师在白板上画系统架构"
纯装饰分隔线alt="装饰线条"alt=""(空值,让读屏跳过)

几个要点:

  • 别写「一张图片 / 截图 / 照片」<img> 元素本身已经告诉读屏「这是图」,再念一遍是噪音;
  • 图标按含义写:放大镜写 alt="搜索"、齿轮写 alt="设置",而不是描述形状;
  • 图表 / 截图写结论:传达「从图里能看出什么」,而不是「图里有几根线」。

装饰图:alt="" 而非省略

html
<!-- ✅ 装饰图:空 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> 写上 widthheight

html
<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 就能既响应式又不抖动:

css
img {
  height: auto; /* 高度按宽高比自动算,避免变形 */
  max-width: 100%; /* 不超出容器 */
}

loading:原生懒加载

loading 控制图片何时开始下载:

html
<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 里假设所有图都就绪。

decodingfetchpriority:两个微优化

html
<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>

html
<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 不够——下一页进入 响应式图片