直接修改 的 srcset 或 media 属性不会触发浏览器重新匹配媒体查询,因匹配仅发生在初始渲染或窗口 resize 时;实现交互需重建整个 结构或改用 动态更新 srcset 和 sizes。

<picture></picture> 本身不支持 JavaScript 动态切换 <source></source> 的匹配逻辑——浏览器在解析 HTML 阶段就完成了媒体查询匹配和资源选择,后续 JS 修改 srcset 或 media 属性不会触发重新评估。
为什么直接改 <source></source> 的 srcset 没用
浏览器只在初始渲染或窗口 resize 时检查 <source></source> 的 media 条件,并按顺序选取第一个满足的源。JS 修改已存在的 <source></source> 属性(比如 el.srcset = "new.jpg")不会触发重匹配,<img> 仍显示原来选中的那张图。
- 即使你用 JS 改了
<source></source>的srcset,浏览器也不会重新走一遍匹配流程 -
window.matchMedia()可以监听媒体变化,但无法主动“触发”<picture></picture>重选 - 强行替换
<img>的src会绕过<picture></picture>的语义和响应式逻辑,失去格式/尺寸适配能力
真正能交互的方案:用 JS 控制整个 <picture></picture> 结构
想实现“点击按钮切换为高清图”“用户偏好切换 WebP/AVIF”这类交互,必须让 JS 重建或替换整个 <picture></picture> DOM,而不是修修补补单个属性。
- 把不同配置的
<picture></picture>写成字符串模板,或提前藏在<template></template>里 - 交互触发时,用
element.innerHTML = newPictureHTML或replaceWith()替换整块结构 - 确保新结构中
<img>的alt、loading、decoding等属性与原结构一致,避免可访问性退化
示例:
<button id="switch-to-hd">切换高清</button><br><picture id="main-pic"><br><source srcset="cat-small.jpg" media="(max-width: 768px)"><br><source srcset="cat-medium.jpg" media="(min-width: 769px)"><br> @@##@@<br></source></source></picture>
JS 做法:
document.getElementById("switch-to-hd").addEventListener("click", () => {<br> const hdPic = `<br><picture><br><source srcset="cat-hd-small.webp" type="image/webp" media="(max-width: 768px)"><br><source srcset="cat-hd-medium.webp" type="image/webp" media="(min-width: 769px)"><br><source srcset="cat-hd-small.jpg" media="(max-width: 768px)"><br><source srcset="cat-hd-medium.jpg" media="(min-width: 769px)"><br> @@##@@<br></source></source></source></source></picture>`;<br> document.getElementById("main-pic").replaceWith(...new DOMParser().parseFromString(hdPic, "text/html").body.children);<br>});
更轻量的替代:用 JS 配合 srcset + sizes 动态更新 <img src="cat-fallback.jpg" alt="一只猫">
如果只是想根据用户操作(如缩放级别、主题切换)加载不同分辨率或格式的图,且不需要 <source></source> 的媒体条件判断,直接操作 <img src="cat-hd-fallback.jpg" alt="一只猫(高清)"> 的 srcset 和 sizes 更简单可靠。
-
<img>的srcset在 JS 中修改后,浏览器会立即触发新的资源选择(只要sizes正确) - 注意:必须同时更新
sizes,否则浏览器无法知道当前图片容器宽度,可能选错分辨率 - 适合场景:暗色模式切换图片、手动缩放时切高 DPI 图、A/B 测试不同压缩质量
例如:
const img = document.querySelector("img[data-dynamic]");<br>img.srcset = "photo-1x.jpg 1x, photo-2x.jpg 2x";<br>img.sizes = "(max-width: 600px) 100vw, 50vw"; // 必须同步更新
真正的难点不在语法,而在于你得明确:交互目标是“覆盖浏览器默认响应逻辑”,还是“补充它”。前者必须重建 <picture></picture>,后者往往用 <img> + JS 就够了——别为了用标签而硬套标签。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











