标签无法基于网络状况自动选图,因其media属性仅支持css媒体特性、type属性只校验mime类型;唯一可靠方案是用javascript读取navigator.connection.downlink或effectivetype动态设置src或srcset。

picture 标签本身不感知网络状况,无法直接响应 4G/3G/离线等条件;浏览器原生不支持基于 navigator.connection.effectiveType 的自动图片切换 —— 所有“按网速选图”方案都必须依赖 JavaScript 配合 src 或 srcset 动态写入。
为什么 <picture></picture> 的 media 和 type 都不适用于网络判断
media 属性只认 CSS 媒体特性(如 width、prefers-color-scheme),对 connection、save-data 等非标准媒体功能完全无视;type 只校验 MIME 类型支持,和带宽无关。即使你写 media="(update: slow)" 或 type="image/low-bandwidth",浏览器会直接跳过该 <source></source>,最终只加载 <img> 的 fallback。
常见错误现象:
- Network 面板里始终只看到一张图被请求,不管 DevTools 里怎么切“Throttling”
- 用
matchMedia("(update: slow)")返回matches === false,说明该查询根本未被实现 - 把
loading="lazy"误当成“按网速加载”,它只控制时机,不控制资源选择
真正可行的 JS 方案:用 navigator.connection + 动态 src
现代浏览器(Chrome 61+、Edge 79+、Firefox 80+)暴露了 navigator.connection API,可读取 effectiveType("slow-2g"、"2g"、"3g"、"4g")和 downlink(Mbps)。这是唯一可靠依据。
实操建议:
- 在
<picture></picture>外层保留语义结构,但所有<source></source>和<img>先不设srcset或src,用占位属性如data-srcset-low="..."、data-srcset-high="..."存储备用路径 - 页面加载后立即检查:
if ("connection" in navigator && navigator.connection.effectiveType),再根据值决定写入哪组资源 - 优先使用
downlink 判断弱网,比 <code>effectiveType === "2g"更稳定(后者在部分安卓 WebView 中不可靠) - 务必监听
navigator.connection.onchange,网络切换时重新设置<img>的src,避免用户从 WiFi 切到地铁后仍加载高清图
示例逻辑(不依赖框架):
const img = document.querySelector("picture img");
const lowRes = img.dataset.srcsetLow;
const highRes = img.dataset.srcsetHigh;
function setImgSrc() {
const isLowBandwidth = navigator.connection?.downlink
<h3>更轻量的兜底策略:用 <code>Save-Data</code> HTTP 头 + 服务端协商</h3>
<p>如果前端 JS 不可控(如 CMS 渲染页),可依赖客户端发送的 <code>Save-Data: on</code> 请求头。服务端识别后,返回已压缩的图片 URL,再由 <code><picture></picture></code> 按常规方式加载 —— 这时 <code><picture></picture></code> 才真正“起作用”。</p>
<p>关键点:</p>
-
Save-Data是 Chrome/Edge/Opera 原生支持的标头,iOS Safari 和 Firefox 不支持,不能单独依赖 - 服务端需提前生成并存储两套图源(如
/img/photo-low.jpg和/img/photo-high.jpg),不能临时压缩 - CDN 必须透传
Save-Data头,否则边缘节点无法做路由决策 - 仍需在 HTML 中为两种情况分别准备
<source></source>,例如:<source media="(max-width: 768px)" srcset="/img/photo-low.jpg"></source>和<source media="(max-width: 768px)" srcset="/img/photo-high.jpg"></source>,靠服务端响应动态替换整个<picture></picture>片段
最容易被忽略的是:没有网络状况的“实时反馈”。用户切到弱网后,已渲染的图片不会自动替换,必须手动触发重载或监听 change 事件;而服务端方案又受限于客户端兼容性。真正落地时,得把 JS 方案当主线,Save-Data 当补充,别指望 <picture></picture> 自己“聪明起来”。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











