image-set()仅适用于CSS background-image,不支持<img>标签;需同时满足真实多倍图、显式background-size、容器尺寸固定及构建路径存在才生效。

image-set() 不能直接用在 HTML 编辑器的 <img> 标签里,它只对 CSS 的 background-image 生效。如果你正在开发或定制一个富文本编辑器(比如基于 contenteditable 的编辑器),想让其中的图标、工具栏按钮、加载占位图等在 Retina 屏上清晰显示,就得靠 CSS 背景图 + image-set() 配合显式尺寸控制。
为什么编辑器里的图标用 image-set() 容易糊
常见错误是只写了 image-set(),但没配 background-size 或容器尺寸不固定。比如工具栏按钮用 div 实现,CSS 写成:
button.format-bold {
background-image: image-set(url("bold.png") 1x, url("bold@2x.png") 2x);
}这会糊——因为:
- 没设
background-size,浏览器默认按图片原始尺寸渲染,bold@2x.png是 48×48px,就会撑开成 48px 高,而不是设计稿要求的 24px - 父容器没设宽高,
contenteditable区域或浮动工具栏可能流式布局,导致像素不对齐 -
bold@2x.png实际是 PS 放大出来的假高清图(物理尺寸没翻倍),image-set()只选图,不缩放不修复
image-set() 在编辑器 UI 中的正确写法
以一个 24px×24px 的加粗按钮图标为例,必须同时满足四个条件:
立即学习“前端免费学习笔记(深入)”;
- 准备真实尺寸的图:
bold-24.png(24×24px)、bold-48.png(48×48px) - 写 fallback:
background-image: url("bold-24.png");放在前面 - 再写
image-set(),且 1x/2x 必须都带:background-image: image-set(url("bold-24.png") 1x, url("bold-48.png") 2x); - 强制尺寸对齐:
background-size: 24px 24px; width: 24px; height: 24px;
完整规则示例:
.toolbar button.bold {
width: 24px;
height: 24px;
background-image: url("bold-24.png");
background-size: 24px 24px;
background-repeat: no-repeat;
}
@supports (background-image: image-set(url(a) 1x)) {
.toolbar button.bold {
background-image: image-set(
url("bold-24.png") 1x,
url("bold-48.png") 2x
);
}
}Firefox 和旧 Safari 下为什么还是 1x 图
image-set() 在 Firefox 中完全不解析(截至 2026 年 6 月仍需前缀或不支持),Safari 15.0–15.3 虽返回 @supports true,但静默跳过 2x 声明。所以仅靠 @supports 检测不可靠。
真正兜底要靠媒体查询,且顺序必须在 @supports 块之后:
@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 2dppx) {
.toolbar button.bold {
background-image: url("bold-48.png");
}
}注意两点:
- 不要用
192dpi,2dppx更准确,避免 DPI 单位换算误差 - 媒体查询里也要重写
background-size: 24px 24px,否则bold-48.png会按 48px 渲染
构建工具路径处理常被忽略的坑
Vite、Webpack 默认不会识别 image-set() 里的字符串为资源引用。写成 url("icons/bold@2x.png"),如果构建配置没开启 assetsInclude 或正则匹配 @2x,这个文件根本不会被打包进 dist 目录,结果就是 404 —— 浏览器不会 fallback 到 1x 图,而是留白或报错。
验证方式很简单:
- 打开开发者工具 Network 面板,过滤
bold@2x.png,看是否 200 - 把
image-set()临时改成url("bold-48.png"),确认图能正常加载 - Vite 用户需在
vite.config.ts加:assetsInclude: ["**/*.png", "**/*@*.png"]
最保险的做法:所有 @2x 图统一放在 src/assets/icons/2x/ 下,路径写死,不依赖构建自动重命名。
实际项目里,image-set() 的价值不在“多炫”,而在把多倍图逻辑收束到一行 CSS 里;但它的脆弱点也很明确——缺一不可:图得真高清、尺寸得锁死、fallback 得双保险、路径得真实存在。漏掉任何一环,Retina 屏上看到的就不是清晰,而是模糊或空白。



















