把 PWA 添加到手机桌面后,如果发现图标糊得像打了马赛克,那大概率是你的 site webmanifest icon sizes 配置出了问题。Android 系统并不会自动帮你把高清大图等比缩小,而是会根据你 manifest.json 里的声明,进行一套简单粗暴的裁剪、缩放和遮罩处理。

之前我就踩过这个坑:同一个 PWA,在 Pixel 手机上看着刀锋般锐利,拿到小米或者三星设备上一看,直接变成了一个偏移且模糊的马赛克方块。这根本不是原图画质不行,纯粹是 manifest 配置的锅。

如果你对 manifest 文件本身还不太熟,建议先扫一眼这篇 favicon site.webmanifest 开发指南。今天这篇文章只聊干货:深入拆解 icons 数组,告诉你到底该声明哪些尺寸。

准备工作

准备一张高清源图(起码 512x512 像素起步)和顺手点的文本编辑器。要是手头没源文件,直接去 Mzu favicondl 拿现成 logo 生成一个就行。

手把手配置 Manifest Icons

咱们来搞一套防弹级别的 icons 数组。对于现代 Android 和 PWA 支持,你真正需要关心的只有三个配置项。

1. 192x192 基础 PNG

这是保底尺寸。Android 在大部分常规屏幕的桌面启动器上,用的就是这个尺寸的图标。必须显式声明,别偷懒。

千万别指望浏览器帮你把 512x512 的大图缩放过去。Android 的渲染引擎在缩小时偶尔会抽风,插值算法一跑,你的图标边缘就软了。老老实实提供一个专门的 192x192 PNG 文件。

2. 512x512 高清 PNG

这是开屏闪屏用的图标。PWA 刚启动、service worker 还在加载时,Android 会在白底上展示这张图。如果 manifest 里只能留一个图标,那就留它(不过最好别这么干)。

3. Maskable Icon(重中之重)

Android 13+ 和新版 Chrome OS 都在用自适应图标。如果你不声明 maskable icon,系统就会把你的标准图标强行塞进一个白色圆圈里,视觉效果堪称灾难。

Maskable icons 需要在中心留出“安全区”。设计时必须给四周留足 padding,这样系统不管怎么裁切(圆形、圆角矩形等),都不会切到你的核心 logo。设计层面的细节可以看这篇 maskable icon 设计指南。

完整代码

下面这段 icons 数组,建议直接复制粘贴到你的 manifest.json 里:

{
  "name": "My Awesome App",
  "icons": [
    {
      "src": "/icons/icon-192.png",
      "sizes": "192x192",
      "type": "image/png",
      "purpose": "any"
    },
    {
      "src": "/icons/icon-512.png",
      "sizes": "512x512",
      "type": "image/png",
      "purpose": "any"
    },
    {
      "src": "/icons/icon-maskable-512.png",
      "sizes": "512x512",
      "type": "image/png",
      "purpose": "maskable"
    }
  ]
}

注意 purpose 字段,它告诉系统该怎么用这个文件。如果省略它,浏览器会默认按 any 处理,这会导致你的 maskable icon 被当成普通图标展示,四周带着一大圈尴尬的 padding。

常见踩坑点

代码写对了,该出问题还是出问题。下面是几个最常见的翻车现场。

用单个 'any maskable' 图标糊弄

有些开发者为了省那几 KB 的体积,只声明一个 "purpose": "any maskable" 的图标。千万别这么干。Maskable icon 自带 padding,如果浏览器拿同一个文件去渲染标准 any 图标,你的 logo 在桌面启动器里就会小得可怜。必须拆分成独立文件。

无视安全区

设计了个绝美的 512x512 图标,直接传上去当 maskable 用。结果系统一刀切成圆形,logo 的一半直接没了。做 maskable icons 时,核心图案必须控制在画布中心 80% 的区域(即安全区)内。

sizes 属性和实际尺寸对不上

文件实际是 512x512 像素,但你在 manifest 里写了 "sizes": "192x192",Android 直接懵逼。系统是优先认 manifest 声明的,不会去管实际文件尺寸。一定要核对好字符串和图片的真实分辨率。

大厂是怎么做的

看看 GitHub 的 PWA 就知道了。人家根本没塞十几个不同尺寸的 PNG 进去,就只放了标准的 192、512,外加一个专门的 maskable 版本。这就是目前的最佳实践。不信你自己开 DevTools 看看他们的 manifest 文件。

想研究其他网站的图标策略,可以用 Mzu favicondl 把它们的 manifest 配置抓下来分析,省得你去一堆压缩过的 HTML 里扒拉。

总结

别再傻乎乎地生成一堆图标文件了。你的 site webmanifest icon sizes 数组里只需要三项:192x192、512x512,以及一个 512x512 的 maskable 版本。保持配置干净,守住安全区,你的 PWA 在各种设备上都能拥有原生应用般的质感。