图片标签用 img 还是 picture?img和picture的区别是什么?

AI 概述
日常前端开发中,img 标签适用于同一张图不同分辨率或尺寸的展示,通过 srcset 和 sizes 属性可实现响应式图片。而 picture 标签则更适用于需要按构图区分(Art Direction)或按浏览器能力选择图片格式(如 WebP/AVIF)的场景。picture 本身不展示图片,而是作为选择器,通过多个 source 元素和 img 兜底实现灵活选择。使用时需注意语义、CSS 及懒加载等属性应写在 img 上。合理选择 img 或 picture,可提升页面性能和用户体验。
目录
文章目录隐藏
  1. img 和 picture 对比
  2. img 可以用来做什么?
  3. picture 什么时候用?

图片标签用 img 还是 picture?img 和 picture 的区别是什么?

日常前端开发,我们经常使用 img 标签就够用了,picture 标签是给「更讲究的人」准备的——要么要换图片格式,要么要换构图,不是单纯缩放大小那么简单。

img 和 picture 对比

img 你肯定天天用,最经典那种:

<img src="/images/banner.jpg" alt="首页大图">

它的意思很直接:这里要展示一张图片,浏览器自己去拉这张图。

后来移动端来了,视网膜屏也来了,一个 src 顶不住了,就有了srcset + sizesimg立马变身「会自己挑图的 img」:

<img
  src="/img/avatar-256.jpg"
  srcset="/img/avatar-128.jpg 128w,
          /img/avatar-256.jpg 256w,
          /img/avatar-512.jpg 512w"
  sizes="(max-width: 600px) 64px, 128px"
  alt="用户头像">

这段话的意思大概是: 浏览器你自己看屏幕多宽、DPR 多高,自己选一张最合适的,不用我操心。

picture呢,其实本身不展示任何东西,它更像一个「图片选择器的外壳」,真正展示图片的还是里面那个 img:

<picture>
  <source
    srcset="/img/banner.avif"
    type="image/avif">
  <source
    srcset="/img/banner.webp"
    type="image/webp">
  <img src="/img/banner.jpg" alt="首页大图">
</picture>

浏览器的逻辑是: 从上往下看source,第一个「我看得懂格式、media也匹配」的就选它;都不行,就乖乖用最后的 img。

所以一句话先记住:

只想让同一张图在不同屏幕用不同分辨率 → img + srcset 想彻底换图片格式 / 换构图 / 换一整套资源 → picture

img 可以用来做什么?

很多人一看到「响应式图片」「多分辨率」就条件反射想到picture,其实有点小题大做了。

典型几种只用 img 就能搞定的情况:

  1. 同一张构图,只是分辨率不同(1x / 2x / 3x 屏);
  2. 同一张构图,只是小屏用 200px,大屏用 400px 之类;
  3. 你只是想懒加载、加个loading="lazy"decoding="async"之类。

例如常见头像组件,完全没必要 picture:

<img
  src="/img/avatar-256.jpg"
  srcset="/img/avatar-128.jpg 128w,
          /img/avatar-256.jpg 256w,
          /img/avatar-512.jpg 512w"
  sizes="(max-width: 600px) 48px, 96px"
  loading="lazy"
  decoding="async"
  alt="用户头像">

这个已经是非常健康的一张图片了:

  • 该懒加载的懒加载;
  • 该根据屏幕选分辨率的选分辨率;
  • 语义和无障碍也都有。

很多后台管理系统、简单营销页,做到这个程度,就足够了。

你甚至可以用一点点 JS 做个「低清晰度占位」的小优化:

const img = new Image()
img.src = '/img/banner@2x-blur.jpg'

img.onload = () => {
  const realImg = document.querySelector('#hero-img')
  realImg.src = '/img/banner@2x.jpg'
}

先展示一张模糊的小图,等清晰大图加载好再替换,也完全不需要picture登场。

picture 什么时候用?

两个核心场景,只要你遇到其中之一,基本就该用 picture 了。

1. 要按「构图」区分,而不是按「尺寸」区分(Art Direction)

这个在设计师眼里特别重要: 不是同一张图缩放,而是手机上要裁一块「中间人物」,PC 上要一张「横幅大场景」。

比如移动端要这样:只看中间的人脸 PC 端要那样:左边放文案,右边整张图铺满

这种情况你没法靠srcset搞,因为srcset只能在「同一张图的不同版本」里选。 你得给浏览器完全不同的几张图片,还要配上媒体查询让它自己挑。

<picture>
  <!-- 窄屏:裁切过的竖图,突出人物 -->
  <source
    srcset="/img/hero-mobile.jpg"
    media="(max-width: 600px)">
  <!-- 宽屏:完整大图 -->
  <source
    srcset="/img/hero-desktop.jpg"
    media="(min-width: 601px)">
  <img src="/img/hero-desktop.jpg" alt="产品介绍主图">
</picture>

这里几个点注意下:

  • source的顺序很重要:浏览器从上往下匹配,第一个满足media条件的就停;
  • img是兜底:老浏览器 / 不支持picture的就用它;
  • 所有语义(alt 等)给 img 写,picture 只是个壳。

这就是典型的「Art Direction」,picture 才有的能力。

2. 想按浏览器能力选择图片格式(WebP / AVIF 等)

另一个非常常见:你希望新浏览器用 AVIF / WebP 这种高压缩比的新格式,老浏览器乖乖用JPEG/PNG

这个就必须picture出场了,因为格式选择靠的是type属性:

<picture>
  <source
    srcset="/img/poster.avif"
    type="image/avif">
  <source
    srcset="/img/poster.webp"
    type="image/webp">
  <img src="/img/poster.jpg" alt="活动宣传海报">
</picture>

浏览器做的事可以简单理解成:

  1. 先看第一个source:我支不支持image/avif?支持就用它,不支持就跳到下一个;
  2. 再看第二个:我支不支持image/webp
  3. 都不行,就用 img 的 JPEG。

好处特别实在:

  • 流量能省很多(AVIF / WebP 同画质下体积明显小);
  • 不用自己写 UA 判断脚本,也不用搞「按路径后缀改图片」这种骚操作;
  • 写法很直观,不容易维护崩。

有些东西不管用 img 还是 picture,行为是一样的,或者有一些容易搞错的地方,顺带说一下。

1. 语义与无障碍

  • alt 一定写在img上,picture写了也没用;
  • 屏幕阅读器识别的也是img,不是外面的picture
  • 真正参与 SEO / 图片搜索的也是imgpicture还是那个壳。
<picture>
  <source srcset="/img/logo-dark.svg" media="(prefers-color-scheme: dark)">
  <img src="/img/logo-light.svg" alt="站点 Logo">
</picture>

别把alt写在picture上,这是个真实线上见过好多次的坑。

2. CSS 怎么写?

所有视觉相关的 CSS(宽高、圆角、阴影、object-fit等),依旧是写在 img 上:

.hero-img {
  width: 100%;
  height: auto;
  border-radius: 8px;
  object-fit: cover;
}
<picture>
  <source srcset="/img/hero-mobile.jpg" media="(max-width: 600px)">
  <source srcset="/img/hero-desktop.jpg" media="(min-width: 601px)">
  <img id="hero-img" class="hero-img" src="/img/hero-desktop.jpg" alt="主视觉">
</picture>

不要对着pictureborder-radius之类,大多数时候不会按你想的那样生效。

3. 懒加载、解码、referrerpolicy 等属性

这些和「图片请求」有关的属性,依然是在 img 上配置:

<picture>
  <source srcset="/img/photo.avif" type="image/avif">
  <source srcset="/img/photo.webp" type="image/webp">
  <img
    src="/img/photo.jpg"
    alt="风景照片"
    loading="lazy"
    decoding="async"
    referrerpolicy="no-referrer">
</picture>

浏览器最终还是按img的这些属性去发请求。

日常写页面的时候,可以在脑子里过一下这几个判断:

  1. 这张图只是大小不同 / 清晰度不同?
    • 是 → img + srcset + sizes搞定
  2. 需要不同的裁剪、构图、比例?
    • 是 → picture</code+ 多个source(配 media)+ 一个 img 兜底
  3. 需要按浏览器支持情况切换格式(AVIF/WebP → JPG)?
    • 是 → picture,配type="image/xxx"
  4. 只是SVG图标 / 小 logo?
    • 大概率一个img或直接<svg>内联就够了

你会发现:picture 真正用到的频率没那么高,但一旦遇到该用它的场景,别犹豫,直接上。

有时候我们既想用picture做格式 / 构图选择,又想在 JS 里根据网络情况进一步「降级」一下,比如用户在 2G 网络,就不要上超大图了。

借助 Network Information API(部分浏览器支持),可以做个小增强:

<picture id="hero-picture">
  <source
    srcset="/img/hero-desktop-hd.avif"
    type="image/avif"
    media="(min-width: 1024px)">
  <source
    srcset="/img/hero-mobile.avif"
    type="image/avif"
    media="(max-width: 1023px)">
  <img
    id="hero-img"
    src="/img/hero-mobile.jpg"
    alt="首页主视觉">
</picture>
(function () {
  if (!('connection' in navigator)) return

  const connection = navigator.connection
  const isSlow = connection.effectiveType === '2g' || connection.saveData

  if (!isSlow) return

  // 省流模式:把高分辨率 source 换成轻量版
  const sources = document.querySelectorAll('#hero-picture source')
  sources.forEach(source => {
    const srcset = source.getAttribute('srcset')
    if (!srcset) return
    const low = srcset.replace('-hd', '-low') // 约定好文件名
    source.setAttribute('srcset', low)
  })
})()

这里picture负责格式 / 构图选择,JS 再基于网络情况做一层「换文件名」的小降级,两者配合得还挺舒服。

不搞一堆术语,直接用一句「心法」:

能用 img 解决的,就别上picture; 一旦你开始「换格式」「换构图」,就别硬扛,老老实实picture

实际工作里,你可以这么用:

  • 新项目起步:统一给重要图片加srcset + sizes,先把img用好;
  • 页面有大 Banner、主视觉,让设计师给两套图:手机一套、PC 一套,用picture
  • 性能要求高、有流量成本的业务,再上一层AVIF/WebPpicture方案。

用到这一步,前端图片这块,你就已经比大多数项目细了。剩下再想折腾什么懒加载、骨架屏、渐进式加载,那就是锦上添花的事了。

以上关于图片标签用 img 还是 picture?img和picture的区别是什么?的文章就介绍到这了,更多相关内容请搜索码云笔记以前的文章或继续浏览下面的相关文章,希望大家以后多多支持码云笔记。

「点点赞赏,手留余香」

1

给作者打赏,鼓励TA抓紧创作!

微信微信 支付宝支付宝

还没有人赞赏,快来当第一个赞赏的人吧!

声明:本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权/违法违规/事实不符,请将相关资料发送至 admin@mybj123.com 进行投诉反馈,一经查实,立即处理!
重要:如软件存在付费、会员、充值等,均属软件开发者或所属公司行为,与本站无关,网友需自行判断
码云笔记 » 图片标签用 img 还是 picture?img和picture的区别是什么?

发表回复