(译) 用 2025 年的方法制作 Favicon:3 个icon就搞定多数需求
本文翻译自:How to Favicon in 2025: Three files that fit most needs
发表于:Martian Chronicles
原作者:Andrey Sitnik
现在是时候重新思考如何为现代浏览器打造一套 favicon,告别“图标生成器”的疯狂了。为了仅仅在浏览器标签或触摸屏上显示一个小小的网站标识,前端开发者动辄要应付二十多个静态 PNG 文件。继续阅读,看看如何用更聪明的方式,采用一套极简的图标组合来满足当下的大多数需求。
It’s time to rethink how we cook a set of favicons for modern browsers and stop the icon generator madness. Frontend developers currently have to deal with 20+ static PNG files just to display a tiny website logo in a browser tab or on a touchscreen. Read on to see how to take a smarter approach and adopt a minimal set of icons that fits most modern needs.
极简版
与其提供几十个图标,其实只需要 5 个图标加 1 个 JSON 文件就够了。
Instead of serving dozens of icons, all you need is just five icons and one JSON file.
HTML 中使用的链接如下:
For the browser using HTML:
<link rel="icon" href="/favicon.ico" sizes="32x32">
<link rel="icon" href="/icon.svg" type="image/svg+xml">
<link rel="apple-touch-icon" href="/apple-touch-icon.png"><!-- 180×180 -->
如果你要做 PWA(渐进式 Web 应用),再在 HTML 里加上:
If you’re making a PWA (Progressive Web App), also add this to the HTML:
<link rel="manifest" href="/manifest.webmanifest">
并准备一个 Web App Manifest 文件:
And a file with the web app manifest:
// manifest.webmanifest
{
"icons": [
{ "src": "/icon-192.png", "type": "image/png", "sizes": "192x192" },
{ "src": "/icon-mask.png", "type": "image/png", "sizes": "512x512", "purpose": "maskable" },
{ "src": "/icon-512.png", "type": "image/png", "sizes": "512x512" }
]
}
Maskable 图标需要更大的内边距,安全区域是直径 409 的圆形。可用 maskable.app 检查你的图标。
Maskable icons should have bigger paddings. The safe zone is a 409×409 circle. Use maskable.app to check your icon.
就是这样。如果你想了解我如何得到这个结论、做了哪些取舍、以及如何从零一步步做出这套最小图标集,请继续阅读全文。
That’s it. If you want to know how I got here, the compromises I had to make, and how to build a set like this from scratch in a step-by-step fashion, stay tuned in for the rest of the article.
详细版本
所谓完美,不在于可以再添什么,而在于再也无物可减。
Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away.
安东尼·德·圣-埃克苏佩里,《飞行员的奥德赛》
Antoine de Saint-Exupéry — Airman’s Odyssey
favicon(“favorite icon”)自 2000 年代早期就出现了。用户通常期望你的网站具备 favicon——它虽小,却能显著提升专业感。Apple 也已在各类设备上正常展示 favicon。
现实中,一个“图标”往往意味着一整套文件。许多生成器会导出二三十张 PNG 来适配不同设备,但我们可以用更聪明、更简洁的方案。
favicon(“favorite icon” 的缩写)自 2000 年代早期就存在了。我们都见过浏览器标签栏里那些小小的图标,帮助区分已打开的网站。用户通常期望你的网站有 favicon——这种小细节会让人更认真对待你的网站。
The concept of a favicon, which is short for “favorite icon”, has been around since the early 2000s. We’ve all seen those tiny images in our browser’s tab bar which help us differentiate our open websites. Users expect your website to have a favicon. It’s one of those little things that make other people take you seriously.
就连多年来在 Safari 里弱化 favicon 的 Apple,如今也“缴械投降”,已经在所有设备上正常显示它们。
Even Apple, which has always had some kind of aesthetic beef with icons that don’t come from Cupertino, downplaying favicons in Safari for years, has finally given up and now properly displays them across all of its devices.
如果你的网站是面向公众的,它就该有 favicon。可惜的是,用户眼里的“一个图标”,在实现上往往是一整套文件。
If you have a public-facing website, it has to have a favicon. Sadly, what users perceive as one icon is actually a lot of them.
因此,人们常把为适配愈加繁杂的设备/屏幕而生成文件的苦差事交给图标生成器。没有哪个清醒的人愿意花数小时手工导出这些文件。我们是来做网站的,并不是来取悦浏览器厂商。
So, it’s common to offload the grueling task of generating these necessary files for an ever-growing list of screens and devices to favicon generator tools. No one in their right mind would ever want to spend hours creating them by hand. We’re here to build websites, after all, not to make browser vendors happy.
作为 NanoID 的作者与极简开源的倡导者,我更愿意换个角度思考:网站图标的最有效组合是什么?哪些格式已经过时?在哪些地方可以做出小小的妥协以替代某些类型?
As a creator of NanoID and a proponent of minimalistic open source, I tend to think in a slightly different direction. What is the most efficient set of website icons? Which formats are outdated? Which icon types can be replaced with small compromises?
于是,我整理出一份“最小清单”,力求在各种场景与各类浏览器上都能工作——极少数边缘案例也许不够完美,但依然可用。
Thus, I set out to create a minimal list of favicons that will work in all cases and in all browsers—barring some edge cases—and even then, this will still work, just not 100% perfectly.
终极 Favicon 方案
与其为不同尺寸导出大量位图,不如依赖 SVG 与浏览器降采样。
— favicon 的下载在后台进行,不影响首屏性能。
— 对 Logo 这类图形,SVG 往往比 PNG 体积更小。
— 仅需少量 PNG 时,可以深度压缩,照顾有限流量用户。
下面给出覆盖主流设备与浏览器的最小集合:
The Ultimate Favicon Setup Instead of creating many images with different sizes, I decided to rely on SVG and browser downscaling. If you’re concerned about performance, I’m here to set the record straight:
Browsers download favicons in the background, so a bigger favicon image does not affect website performance. SVG is a great way to reduce image size for images that aren’t supposed to be bitmaps in the first place; for many logos the resulting file will be much smaller than a PNG. With just three PNG images in this minimum set, you can use advanced tools to optimize their size. This solves a problem for Internet users that don’t have unlimited data plans. Now I’ll reveal the minimal set of icons that I came up with during my research and practice. This list should work with all popular browsers and devices, both old and new.
I. 兼容旧浏览器的 favicon.ico
ICO 可在单一文件中打包多分辨率。推荐仅使用 32×32;若 16×16 不清晰,请单独制作小尺寸版本。务必确保 /favicon.ico
可直取;并在 HTML 中为 ICO 链接添加 sizes=“32x32”
,以绕过 Chrome 偏向 ICO 的 Bug。
I. favicon.ico for legacy browsers ICO files actually have a directory structure and can pack files with different resolutions. I recommend sticking to a single 32×32 image, unless the one you have doesn’t downscale well to 16×16 (if it becomes blurry, for instance). In that case, you can ask your designer to come up with a special version of the logo that’s tailored to fit small pixel grids.
Don’t get smart with the folder static asset folder structure and cache busters. https://example.com website should have a favicon on https://example.com/favicon.ico. Some tools, like RSS readers, just request /favicon.ico from the server and don’t bother looking elsewhere.
We need sizes=“32x32” for <link>
to .ico file in order to fix the Chrome bug where it chooses an ICO file over an SVG.
II. 单个 SVG(支持明暗主题)
SVG 在大尺寸更高效,现代浏览器广泛支持。使用 <link rel=“icon” type=“image/svg+xml”>
引用;在 SVG 内用 @media (prefers-color-scheme: dark)
切换亮/暗主题。
II. A single SVG icon with a light/dark version for modern browsers SVG is a vector format that describes curves instead of pixels. At large sizes, it’s more efficient than raster images. As of this writing, 72% of all browsers support SVG icons.
Your HTML page should have a <link>
tag in its <head>
with rel="icon"
, type="image/svg+xml"
and with the href containing a link to the SVG file as attributes.
SVG is an XML format and can contain a <style>
tag to describes CSS. As with any CSS, it can contain media queries like @media (prefers-color-scheme: dark). This will allow you to toggle the same icon between light and dark system themes.
III. Apple 设备使用 180×180 PNG
用于添加到主屏幕的 Apple Touch Icon:建议 180×180。可适当留白提高观感。
III. 180×180 PNG image for Apple devices
The Apple touch icon is an image that Apple devices will use if you add the webpage as a shortcut to your home screen on an iPhone or iPad. Your HTML page should have <link rel="apple-touch-icon" href="apple-touch-icon.png">
tag inside <head>
.
Since iOS 8+, iPads have required an image with a 180×180 resolution. Other devices will downscale it, but if we provide the source with a high-enough quality, the downscaling won’t hurt the end-user (I’ll come back to this later).
Small note: an Apple touch icon will look better if you place 20px padding around the icon and add some background color. You can use any image editor to do this.
IV. Android 的 Web App Manifest
在 HTML 中引入 manifest.webmanifest
;其中包含 192×192、512×512(maskable)与 512×512(启动屏)图标。maskable 需更大留白,安全区为直径 409 的圆。
IV. Web app manifest with 192×192 and 512×512 PNG icons for Android devices
A web app manifest is a JSON file containing all the details for a browser to install your website as a system application. This format came about from Google via its PWA initiative.
Your HTML page should have a <link rel="manifest" href="path.webmanifest">
tag with a link to the manifest file.
The manifest should have an icon field that links to three icons: 192×192, for display on the home screen, a 512×512 maskable icon for different Android launchers, and a 512×512 which will be used as a splash screen while the PWA is loading.
The maskable icon should have bigger paddings around the icon so it can be cropped by the launcher to fit its design. The safe zone is a central circle of 409×409. You can use maskable.app to check your icon.
{
"icons": [
{
"src": "/icon-192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "/icon-mask.png",
"type": "image/png",
"sizes": "512x512",
"purpose": "maskable"
},
{
"src": "/icon-512.png",
"type": "image/png",
"sizes": "512x512"
}
]
}
还有没覆盖的吗?
确实还存在一些更小众的“口味”。下面逐一过一眼,也顺便和它们道别。
Did we forget anyone? There are, of course, more favicon flavors out there, some of them quite obscure, so let’s see how our setup fares with them. Maybe, it’s time to say farewell to some of the less successful formats out there.
Windows 磁贴图标
旧版 Edge 曾支持“固定到开始菜单”的专用图标;近期 Windows 版本已不再需要。
Windows Tile Icon Microsoft Edge used to support a special icon format to pin websites to the start menu. For recent versions of Windows, this is no longer required.
Safari Pinned Icon
早期要求单色 SVG;Safari 12 起常规 favicon 也可用于“固定标签”。apple.com 也不再用 mask-icon。
Safari Pinned Icon Safari formerly had a requirement of SVG monochrome icon for pinned tabs. However, since Safari 12, we can use a regular favicon for pinned tabs. Even apple.com doesn’t use the mask-icon anymore.
rel=“shortcut”
不少旧教程会用 rel=“shortcut icon”
;这个关系从来不是标准——直接用 rel=“icon”
即可。
<link rel="shortcut icon" href="/favicon.ico" sizes="32x32">
rel=“shortcut” A lot of (now outdated) tutorials will include a favicon.ico into HTML like this:
Be warned that shortcut is not, and never has been, a valid link relation. Read this amazing article by Mathias Bynens from ten years ago that explains why we never needed shortcuts and why rel="icon"
is just fine.
Opera Coast
过去在 iOS 上的实验浏览器,要求 228×228 专用图标;2017 年已下架,可忽略。
Opera Coast In the past, Opera Coast, an experimental browser for iOS, required a special 228×228 icon. This browser left the App Store in 2017, and I doubt it survived the multiple iOS updates since that time.
和这些“退役格式”告别后,我们来动手做一套真正实用的“终极 favicon”。
Now, as we wave good-bye to our fallen comrades, let’s see how to produce an ultimate favicon set for those who are still standing.
如何构建
只需 6 步,从一个方形 SVG 开始:
How to build our Ultimate Favicon Set Here’s how to build our ultimate, minimalistic favicon set in six quick steps. All you need to start is an SVG file for the logo that you want to use.
步骤 1:准备 SVG
确保图像为正方形,调整文档尺寸并居中 Logo,保存为 icon.svg
;可在 SVG 内加样式以适配暗色主题。
Step 1: Prepare the SVG Be sure that the SVG image is square. Open the source file in your system viewer and check the image’s width and height. It’s easy to adjust the SVG size using any SVG editor. In Inkscape, you can change document size by selecting File → Document Properties and then center the logo using Object → Align and Distribute.
Save your file as icon.svg. Now let’s fiddle with our SVG and make it play well with modern system themes. Ask your designer how the colors should be inverted for a dark theme (for B&W logos, you just change black to white).
Now, open your SVG file in a text editor. Find a <path>
with a dark or missing fill. Add a CSS media query that will trigger on theme changes and change fill to the colors you want:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 500">
+ <style>
+ @media (prefers-color-scheme: dark) {
+ .a { fill: #f0f0f0 }
+ }
+ </style>
- <path fill="#0f0f0f" d="…" />
+ <path class="a" fill="#0f0f0f" d="…" />
</svg>
同样可以用该媒体查询为 SVG favicon 添加 P3 广色域配色。
You may also use this media query technique with SVGs to add wide-gamut P3 colors to your favicons.
步骤 2:创建 ICO
在 GIMP 导出 32×32 的 favicon.ico
(32bpp、8 位 alpha、无调色板);或用 Inkscape + ImageMagick 转换。
Step 2: Create an ICO file Open your icon.svg file in a raster graphics editor. I recommend GIMP; it’s free and multi-platform.
Accept rendering SVG to raster. Set the width and height to be 32 pixels. Export file to favicon.ico using 32 bpp, 8-bit alpha, no palette settings.
If you do not have GIMP you can install Inkscape and ImageMagick and convert SVG to ICO in the terminal:
inkscape ./icon.svg --export-width=32 --export-filename="./tmp.png"
# In Windows call `magick convert ./tmp.png ./favicon.ico`
convert ./tmp.png ./favicon.ico
rm ./tmp.png
把图缩到 16×16 检查可读性;若太糊请单独绘制小尺寸版本。
Scale the image down to 16×16 and check the icon visibility. If it has become too blurry, it would be better to ask your designer for a custom tiny version of the logo.
如需在 ICO 内同时包含 16×16,可在 GIMP 添加 16×16 图层并导出,或用 ImageMagick 合成。
To include a separate 16×16 version of an icon:
Open favicon.ico with the 32×32 icon. Create a new layer with a 16×16 size. Put the 16×16 version of an icon into this layer. Export the file. GIMP will save each layout as a separate version of the icon. Or you can do the same in ImageMagick by:
convert ./icon-32.png ./icon-16.png ./favicon.ico
步骤 3:导出 PNG
导出 icon-512.png
、icon-192.png
;Apple Touch Icon:图像 140×140、画布 180×180;maskable:图像 409×409、画布 512×512,并在 maskable.app 检查。
Step 3: Create PNG images Open your source SVG file in a raster graphics editor again and create a 512×512 image. Export it as icon-512.png.
Scale the image to 192×192 and export it to icon-192.png. Now scale the image itself to 140×140 and set the canvas to 180×180, and then export it as apple-touch-icon.png.
Then, scale it to 409×409 and increase the canvas to 512×512, and export it as icon-mask.png. Check the icon in the maskable.app with different masks and tune the icon size if needed.
Or you can do the same in Inkscape:
inkscape --export-type="png" --export-width=512 --export-filename="./icon-512.png" ./icon.svg
inkscape --export-type="png" --export-width=192 --export-filename="./icon-192.png" ./icon.svg
步骤 4:优化 PNG 与 SVG
SVG 用 SVGO,位图用 Squoosh(OxiPNG,减色,约 64 色起步再微调)。
npx svgo --multipass icon.svg
Step 4: Optimize PNG and SVG files The best tool for optimizing SVGs is SVGO. To use it, run:
Squoosh is a great web app to optimize raster images:
Open your icon-512.png in Squoosh. Change the Compress setting to OxiPNG. Enable “Reduce palette”. Set 64 colors. Compare the before/after by moving the slider. If you see a difference, increase the number of colors. Save the file. Repeat these steps for icon-192.png and apple-touch-icon.png.
步骤 5:在 HTML 中引用
需要在 HTML 中加入 favicon.ico
与 apple-touch-icon.png
的链接。
You need to add links to favicon.ico
and apple-touch-icon.png
into your HTML.
静态 HTML 示例:
For static HTML:
<title>My website</title>
<link rel="icon" href="/favicon.ico" sizes="32x32">
<link rel="icon" href="/icon.svg" type="image/svg+xml">
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
生产环境建议使用打包器生成指纹文件名(在名称里包含哈希)。如果使用 Webpack 与 HtmlWebpackPlugin:
We recommend using a bundler to generate cache busters (include the file’s hash as a fingerprint). If you are using Webpack with HtmlWebpackPlugin:
先创建一个 index.html
模板。
Create an index.html
template.
在插件选项中引用该模板:
Add the template to the plugin options:
new HtmlWebpackPlugin({ template: "./view/index.html" });
定义包含这些链接的 HTML 模板(也可用你喜欢的任意模板语法):
Define an HTML template with links (you can use your templating language of choice):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>My website</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="icon" href="/favicon.ico" sizes="32x32">
<link rel="icon" type="image/svg+xml" href="<%=
require('./icon.svg').default
%>">
<link rel="apple-touch-icon" href="<%=
require('./apple-touch-icon.png').default
%>"
>
</head>
<body></body>
</html>
用 copy-webpack-plugin 复制 favicon.ico
,避免加 hash。
Use copy-webpack-plugin to copy favicon.ico
without adding a hash to the file name.
加分项:为预发/测试环境使用不同图标,避免误操作。
Bonus tip: use a separate icon for staging to avoid confusion.
准备 favicon-dev.ico
与 icon-dev.svg
(或其它明显区分的版本)。
Create favicon-dev.ico
and icon-dev.svg
(or any visually distinct variants).
在模板中根据 process.env.NODE_ENV
切换:
In your template, switch based on process.env.NODE_ENV
:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>My website</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
- <link rel="icon" href="/favicon.ico" sizes="32x32">
+ <link rel="icon" sizes="32x32" href="<%=
+ process.env.NODE_ENV === 'production'
+ ? '/favicon.ico'
+ : require('./favicon-dev.ico').default
+ %>">
<link rel="icon" type="image/svg+xml" href="<%=
- require('./icon.svg').default
+ process.env.NODE_ENV === 'production'
+ ? require('./icon.svg').default
+ : require('./icon-dev.svg').default
%>">
<link rel="apple-touch-icon" href="<%=
require('./apple-touch-icon.png').default
%>">
</head>
<body></body>
</html>
步骤 6:创建 Web Manifest
为静态 HTML 创建一个名为 manifest.webmanifest
的 JSON 文件:
For static HTML, create a JSON file named manifest.webmanifest
:
{
"name": "My website",
"icons": [
{ "src": "/icon-192.png", "type": "image/png", "sizes": "192x192" },
{ "src": "/icon-mask.png", "type": "image/png", "sizes": "512x512", "purpose": "maskable" },
{ "src": "/icon-512.png", "type": "image/png", "sizes": "512x512" }
]
}
在 HTML 中引入该 Manifest 与图标:
Link it in your HTML:
<title>My website</title>
<link rel="manifest" href="/manifest.webmanifest">
<link rel="icon" href="/favicon.ico" sizes="32x32">
<link rel="icon" href="/icon.svg" type="image/svg+xml">
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
如果使用 Webpack,可以借助 webpack-pwa-manifest 插件:
With Webpack, you can use the webpack-pwa-manifest
plugin:
plugins: [
…,
new WebpackPwaManifest({
name: 'My website',
icons: [
{ src: resolve('./icon-192.png'), sizes: '192x192' },
{ src: resolve('./icon-mask.png'), sizes: '512x512', purpose: 'maskable' },
{ src: resolve('./icon-512.png'), sizes: '512x512' }
]
})
]
“像火星风声的无线电波”
Radio wave representing wind sounds on Mars
感谢阅读!借助现代 Web 标准,打造“终极 favicon 集合”其实很直接。即便手工跟着以上步骤做也不费时——若能做成自动化工具就更棒了。欢迎在 X/Twitter 联系作者一起构建!
Thank you for reading! As you can see, with modern web standards, creating our Ultimate Favicon Set is quite straightforward. Even though following the steps manually shouldn’t take much of your time, having an automated tool to do the same will make things even more amazing! Feel free to ping me on Twitter if you’re willing to build one; I’ll be more than happy to help!
原文版权所有:Andrey Sitnik
翻译版权所有:macguffin