Retina 显示屏图像制作 - 在高 DPI 屏幕上实现清晰显示
为什么图像在 Retina 显示屏上模糊 - 理解设备像素比
Retina 显示屏 (Apple 商标) 和高 DPI 屏幕使用多个物理像素来渲染一个 CSS 像素。这个比率称为设备像素比 (DPR)。DPR 为 2x 的设备使用 4 个物理像素 (2×2) 来显示 1 个 CSS 像素,DPR 为 3x 的设备使用 9 个物理像素 (3×3)。
为什么标准图像会模糊:
当一张 200×200 像素的图像在 DPR 2x 的设备上以 200×200 CSS 像素显示时,浏览器必须将 200 个像素拉伸到 400 个物理像素上。这种放大导致图像模糊,因为没有足够的像素信息来填充物理像素。
解决方案:
提供 2 倍或 3 倍分辨率的图像。对于 200×200 CSS 像素的显示区域:
- 1x 设备: 需要 200×200 px 图像
- 2x 设备: 需要 400×400 px 图像
- 3x 设备: 需要 600×600 px 图像
当前设备 DPR 分布:
- DPR 1x: 旧款桌面显示器 (逐渐减少)
- DPR 2x: 大多数现代笔记本电脑、iPad、中端智能手机
- DPR 3x: 高端智能手机 (iPhone Pro 系列、旗舰 Android)
- DPR 4x: 少数超高分辨率设备
实际上,支持 1x 和 2x 即可覆盖绝大多数用户。3x 支持对于面向高端移动用户的网站有价值,但收益递减。
使用 srcset 进行分辨率切换 - 基本 HTML 实现
HTML 的 srcset 属性让浏览器根据设备 DPR 自动选择最佳分辨率的图像。这是实现 Retina 支持最基本的方法。
像素密度描述符语法:
<img src="logo-1x.png" srcset="logo-1x.png 1x, logo-2x.png 2x, logo-3x.png 3x" alt="Logo" width="200" height="50">
浏览器根据设备 DPR 选择对应的图像文件。在 2x 设备上自动下载 logo-2x.png。
宽度描述符语法:
<img src="photo-800.jpg" srcset="photo-400.jpg 400w, photo-800.jpg 800w, photo-1200.jpg 1200w, photo-1600.jpg 1600w" sizes="(max-width: 600px) 100vw, 800px" alt="照片">
宽度描述符更灵活,浏览器综合考虑显示宽度和 DPR 来选择。在 800px 宽的容器中,2x 设备会选择 1600w 的图像。
两种语法的选择:
- 像素密度描述符 (1x, 2x): 适合固定尺寸的元素 (Logo、图标、头像)
- 宽度描述符 (w): 适合响应式布局中尺寸变化的图像 (文章配图、产品图)
注意事项:
- 始终设置
width和height属性防止布局偏移 src属性作为不支持srcset的旧浏览器的回退- 不要为所有图像都提供 3x 版本 - 文件大小增长显著而视觉改善有限
Picture 元素与艺术指导 - 按设备提供不同图像
<picture> 元素比 srcset 提供更精细的控制,可以根据设备特性提供完全不同的图像,而不仅仅是不同分辨率。
结合格式和分辨率:
<picture> <source type="image/avif" srcset="hero-2x.avif 2x, hero-1x.avif 1x"> <source type="image/webp" srcset="hero-2x.webp 2x, hero-1x.webp 1x"> <img src="hero-1x.jpg" srcset="hero-2x.jpg 2x" alt="首页横幅"></picture>
这同时实现了格式协商 (AVIF > WebP > JPEG) 和分辨率切换。
艺术指导与 DPR 结合:
在不同设备上不仅改变分辨率,还改变图像内容:
<picture> <source media="(max-width: 600px)" srcset="product-mobile-2x.jpg 2x, product-mobile-1x.jpg 1x"> <source media="(min-width: 601px)" srcset="product-desktop-2x.jpg 2x, product-desktop-1x.jpg 1x"> <img src="product-desktop-1x.jpg" alt="产品图"></picture>
移动端显示产品特写 (裁切版),桌面端显示产品全貌,两者都提供 2x 版本。
实用建议:
- 对于大多数图像,
srcset配合宽度描述符已经足够 <picture>主要用于需要不同裁切或不同格式的场景- 过度使用
<picture>会增加 HTML 复杂度和维护成本
CSS 高 DPI 支持 - image-set() 与背景图优化
CSS 背景图像和内容图像同样需要高 DPI 显示支持。image-set() 函数使 CSS 能够根据设备分辨率选择不同的图像。
image-set() 语法:
.hero { background-image: image-set(url("bg-1x.jpg") 1x, url("bg-2x.jpg") 2x); }
浏览器根据设备 DPR 自动选择合适的背景图像。
媒体查询方式 (兼容性更好):
.logo { background-image: url("logo-1x.png"); }@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) { .logo { background-image: url("logo-2x.png"); background-size: 200px 50px; }}
关键注意事项:
- 使用
background-size确保高分辨率图像以正确的 CSS 尺寸显示 min-resolution: 192dpi等同于 2x DPR-webkit-min-device-pixel-ratio是 WebKit 前缀,用于兼容旧版 Safari
SVG 作为替代方案:
对于图标、Logo 和简单图形,SVG 是最佳的高 DPI 解决方案。SVG 是矢量格式,在任何分辨率下都保持清晰,无需提供多种尺寸。一个 SVG 文件即可完美适配所有 DPR。
CSS 生成的图形:
渐变、边框、阴影等 CSS 生成的视觉效果天然支持高 DPI,无需额外处理。尽可能使用 CSS 替代图像可以减少 HTTP 请求并自动适配所有分辨率。
图像导出工作流 - 高效生成多分辨率版本
建立高效的 Retina 图像生成工作流程可以直接降低运营成本。手动多分辨率导出既耗时又容易出错。
设计工具导出:
- Figma: 在导出设置中选择 1x、2x、3x 同时导出。支持批量导出所有资源
- Sketch: 使用导出预设配置多种分辨率。可通过插件自动化
- Adobe XD: 导出面板支持多种缩放比例同时输出
构建时自动生成:
使用 Sharp 等图像处理库在构建流水线中自动生成多种分辨率:
const sizes = [1, 2, 3]; // DPR 倍数const baseWidth = 400; // 基础 CSS 宽度for (const dpr of sizes) { await sharp('input.jpg') .resize(baseWidth * dpr) .jpeg({ quality: dpr === 1 ? 80 : 70 }) .toFile(`output-${dpr}x.jpg`);}
质量设置策略:
高分辨率图像可以使用较低的压缩质量而不影响视觉效果。因为像素密度更高,压缩伪影在物理尺寸上更小,不易被察觉:
- 1x 图像: 质量 80-85%
- 2x 图像: 质量 65-75%
- 3x 图像: 质量 55-65%
这种策略可以显著减小 2x/3x 图像的文件大小,同时保持视觉质量。
性能平衡 - 管理高 DPI 支持的成本
高 DPI 支持直接提升图像质量,但会增加文件大小成本。2x 图像的像素数约为 1x 的 4 倍 (宽度和高度各翻倍),文件大小通常增加 2-3 倍。需要在质量和性能之间找到平衡。
文件大小影响:
- 1x (400×300): 约 40KB (JPEG 质量 80)
- 2x (800×600): 约 100KB (JPEG 质量 70)
- 3x (1200×900): 约 180KB (JPEG 质量 60)
优化策略:
- 使用现代格式: AVIF 和 WebP 在相同质量下比 JPEG 小 30-50%。2x AVIF 可能比 1x JPEG 还小
- 降低高 DPI 图像质量: 如前所述,2x/3x 图像可以使用更低的压缩质量
- 限制最大 DPR: 对大多数网站,支持到 2x 即可。3x 的视觉改善有限但文件大小增加显著
- 懒加载: 首屏以下的高 DPI 图像使用懒加载,减少初始加载量
何时不需要高 DPI:
- 背景纹理和装饰性图像 - 模糊不明显
- 大面积照片背景 - 用户不会近距离审视
- 视频缩略图 - 点击后会播放视频
监控和测量:
使用 Chrome DevTools 的网络面板检查实际下载的图像尺寸。如果 2x 图像的文件大小导致 LCP 恶化,考虑降低质量或限制为 1.5x。使用 Lighthouse 的图像审计检查是否有过大的图像被发送到不需要的设备。