使用方法
- 在图标内容里填 1~4 个字符。汉字、字母、emoji 都行,示例是汉字「柳」。超过 4 个会被拒绝,因为 16 px 画布上挤 5 个字必然糊成一团。
- 选背景色与前景色,都写成 6 位或 3 位 HEX。示例是
#2563eb配#ffffff,这组对比度约 5.17:1,16 px 下也能分辨。 - 选档位。默认 3 档(16 / 32 / 48),需要高分屏和PWA 就选 5 档。16 与 32 始终包含在内,不会被裁掉。
- 点「生成图标」(或在任一单行框按 Enter)重画。三个预览画布按真实像素尺寸显示,带棋盘格底,方便看清透明区。
- 「下载 favicon.ico」拿走多尺寸容器,「下载 32px PNG」单独拿一档,「复制嵌入代码」把 head 标签与 manifest 一起带走。
这个favicon生成器能解决什么问题
一是一次拿到多档尺寸,不用开三次图。浏览器标签页、Windows 资源管理器书签、旧版 Android 都只吃 16 px,现代高分屏桌面吃 32 px,Windows 任务栏 Alt-Tab 与部分网站收藏图标会取 48 px 以上。用画图软件逐个尺寸导出、再手工拼 ICO 容器,是一件机械且容易错位的事;这个 favicon生成器把 16/32/48/64/128 五档一次画完并按规范拼进一个文件。
二是把「图标做出来了」和「代码怎么写」放在一起。多数人卡住的不是画图,而是不知道 head 里要写哪几行、apple-touch-icon 是什么、manifest 要不要给。本页输出的代码块直接给了三行 link 标签和一份 manifest 骨架,尺寸与文件一一对应。
三是能算出体积,而不是凭感觉。每档的 PNG 字节数是canvas.toBlob 出来的真实值,ICO 头部的 6+16×N 也是按规范算的。示例 3 档合计约 597 字节,5 档约 1516 字节,放在绝大多数站点的首屏请求里都无感。
四是不上传图片也能有图标。本页不提供图片上传入口——站点图标本来就不该用产品截图,文字或单个字母反而更清晰。要把现有 PNG 转成 ICO 容器,请用「PNG转ICO转换器」;要按宽高比裁剪现有图片,请用「按宽高比裁剪图片」;要压缩已有图,请用「图片压缩工具」。
原理与规则说明:ICO 容器怎么拼、PNG 为什么能直接塞进去
ICO 是个容器,不是格式。整个文件分三段:ICONDIR 固定 6 字节(reserved 写 0 占 2 字节、type 写 1 占 2 字节、count 写档位数占 2 字节);接着是 count 个 ICONDIRENTRY,每个固定 16 字节;最后是各档的图像数据块。ICONDIRENTRY 里的 imageOffset 是该档数据在文件中的绝对起始位置,必须在头部算完之后逐档累加偏移——这是最容易写错的一处,偏移差1 字节整个文件就废了。示例 3 档的头部是 6 + 16 × 3 = 54 字节,5 档是 6 + 16 × 5 = 86 字节。
每档 16 字节的字段布局是固定的。width 与 height 各 1 字节(256 像素要用 0 表示,这是规范里的特例,本页最大只到 128,不触发)、colorCount 与 reserved 各 1 字节、planes 与 bitCount 各 2 字节、bytesInRes 与 imageOffset 各 4 字节(小端序,所以要按字节写,不能直接往 DataView 里塞一个 JS number 而不指定 endianness)。
PNG 负载是 Vista 以后才被接受的写法。早期 ICO 里的每档必须是 BMP:BITMAPINFOHEADER 40 字节,加上 w × h × 4 字节的 XOR 像素区,再加一行按 4 字节对齐的 AND 掩码。按这个公式,32 px 一档的 BMP 负载是 40 + 4096 + 128 = 4264 字节,48 px 是 9640 字节。Windows Vista 起支持直接内嵌 PNG 负载,本页就走这条路,实测 32 px 圆环图标只有 180 字节,比同样尺寸的 BMP 小 23.7 倍。
绘制走CanvasRenderingContext2D,导出走 toBlob。每档新建一个边长为 N 的 canvas,填背景色圆角矩形,再用 fillText 画字符,字体按 Math.round(N × 0.62) 像素的 sans-serif 设定——0.62 这个系数是让单字在 N×N 画布里占到约六成高度,留出边距。canvas.toBlob(cb, 'image/png') 拿到的 Blob 就是可直接塞进 ICO 的 PNG 字节。PNG 没有quality 参数,那是 JPEG 与 WebP 才有的,所以本页不提供「导出质量」滑块,避免做成一个完全无效的控件。
data URI 走 base64,会胀三分之一。按 RFC 4648 第 4 节,base64 每 3 字节原始数据变成 4 个字符。示例 32 px 的 180 字节 PNG 编成 240 字符的 data URI,膨胀 1.333 倍。所以能放文件就别内联进 HTML——内联的好处是省一次请求,代价是每个引用点都重复一份字节。
完整示例(数值仅作演示)
示例条件与这个 favicon生成器打开页面时的默认值完全一致:字符「柳」、背景 #2563eb、前景 #ffffff、3 档(16 / 32 / 48)。实测结果如下:
- ICO 头部 54 字节(
6 + 16 × 3),三档 PNG 负载实测 127 / 180 / 236 字节,合计 543 字节; - ICO 总体积约 597 字节(0.58 KB),未压缩 BMP 方案同尺寸要 15032 字节,是它的 25.2 倍;
- 32 px 单独导出 PNG 是 180 字节,转data URI 后 240 字符;
- 切到 5 档时头部变86 字节,负载加 284 + 603 = 887 字节,总体积 1516 字节(1.48 KB);
- 三档画布总像素
16² + 32² + 48² = 256 + 1024 + 2304 = 3584个。
下面这段是示例的真实输出代码,可直接粘进 <head>:
<!-- 把 favicon.ico 放到站点根目录,浏览器会自动请求 /favicon.ico -->
<link rel="icon" href="/favicon.ico" sizes="16x16 32x32 48x48">
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
<link rel="manifest" href="/site.webmanifest">
{
"name": "柳",
"icons": [
{ "src": "/favicon.ico", "sizes": "16x16 32x32 48x48", "type": "image/x-icon" }
]
}
下表是 16 档常用边长的完整对照,数字由同一套 toBlob 逻辑与 BMP 公式算出,前 12 行默认显示,点「加载更多」看后 4 行(20/24/72/96/144/152/180/192/256/512):
| 边长 | 像素数 | 未压缩 BMP 负载 | 本示例 PNG 负载 | base64 字符 | 常见用途 |
|---|---|---|---|---|---|
| 16 px | 256 | 1128 字节 | 127 字节 | 172 | 浏览器标签页书签栏 |
| 32 px | 1024 | 4264 字节 | 180 字节 | 240 | 高分屏标签页与地址栏 |
| 48 px | 2304 | 9640 字节 | 236 字节 | 316 | Windows 任务栏与网站收藏 |
| 64 px | 4096 | 16936 字节 | 284 字节 | 380 | 桌面快捷方式与部分启动器 |
| 128 px | 16384 | 67624 字节 | 603 字节 | 804 | splash 屏与 PWA 大图标 |
| 20 px | 400 | 320 字节 | 98 字节 | 132 | Safari 固定标签页(小尺寸档) |
| 24 px | 576 | 616 字节 | 120 字节 | 160 | macOS 标签页与 Spotlight 建议 |
| 72 px | 5184 | 24376 字节 | 336 字节 | 448 | Windows 大图标视图与浏览器书签 |
| 96 px | 9216 | 36952 字节 | 448 字节 | 600 | Windows 快捷方式图标 |
| 144 px | 20736 | 82960 字节 | 700 字节 | 936 | 旧版 Android 桌面与部分启动器 |
| 152 px | 23104 | 92560 字节 | 752 字节 | 1004 | Android 启动器小尺寸档 |
| 180 px | 32400 | 129880 字节 | 860 字节 | 1148 | iOS apple-touch-icon 缺省档 |
| 192 px | 36864 | 147568 字节 | 912 字节 | 1216 | Android Chrome PWA 清单档 |
| 256 px | 65536 | 262792 字节 | 1244 字节 | 1660 | Windows 超大图标(ICO 里宽高字段写 0) |
| 512 px | 262144 | 1050624 字节 | 2860 字节 | 3816 | PWA 512 大图标,需另出 PNG |
输入范围与对照表
每个字段的范围与超限动作如下,右列是填错时会看到的具体提示:
| 字段 | 允许范围 | 超限或填错时的动作 |
|---|---|---|
| 图标内容 | 1~4 个字符(按 UTF-16 码元计) | 拒绝生成,提示最多 4 个字符及其原因 |
| 背景色 / 前景色 | 3 位或 6 位 HEX,允许带 # | 拒绝生成,提示必须形如 #2563eb |
| 前景背景同色 | 允许但会提示 | 照常生成,同时提示对比度为 1:1 会看不见 |
| 档位 | 3 / 4 / 5 档,含 16 与 32 | 非法值回退到 3 档并在提示里说明 |
| emoji 内容 | 允许,按 2 个码元计 | 超 4 码元即拒绝,需自行减字 |
| canvas 不可用 | 不支持 | 提示浏览器缺少 Canvas 支持,不静默出空图 |
边界与字节数说明
- 每档图像数据的上限是 65535 字节。
bytesInRes字段只有 4 字节但 ICO 规范把它当无符号 32 位用,而 BMP 负载另有一条 65535 字节的实际上限约束。本页生成的图标实测最大 603 字节(128 px),离这个上限有两个数量级的余量,复杂位图另说。 - 128 px 一档的 BMP 负载 67624 字节(66.04 KB),已经超过整个 5 档 PNG 方案(1516 字节)的 44 倍。这就是为什么本页坚持用 PNG 负载:
128² × 4 = 65536字节的像素区本身就很大,压缩后才能进一个合理体积的 favicon。 - 256 px 是 ICO 里的特殊尺寸,在
ICONDIRENTRY的 width/height 字段里要用 0 表示而不是 256。本页档位上限是 128,不涉及这个特例;若要加 256 档,字段必须写 0,否则部分老程序读不出来。 - 内容最多 4 个码元,长度按 UTF-16 计。一个常用 emoji(如 U+1F600)在 JS 里是 2 个码元,所以「😀」占 2 个额度;少数由多个码点组成的 emoji(如带变体选择符的序列)会占 4 个以上,直接触发拒绝。这是
String.length的语义,不是字符实际观感。 - 字体是系统 sans-serif,字形不可控。用
fillText画字,渲染结果取决于操作系统装了什么字体。同一份代码在Windows 和 macOS 上画出的「柳」字边缘不同,笔画粗细也不同。要像素级可控就得改成手绘路径或导入字体文件,本页不做。 - 圆角半径固定为边长的 22%。这是
roundRect的参数选择——iOS 风格图标习惯圆角,但站点图标普遍留小圆角,因为 16 px 下大圆角会让有效图形区太小。22% 在 16 px 上约 3.5 像素,视觉上刚好。 - HEX 大小写与 3 位简写都接受,内部会展开成 6 位再交给
fillStyle。#abc展开成#aabbcc,这是 CSS 颜色规范里的既定规则,不是本页自定的。 - 预览画布是 3 个,不是全部档位都预览。只画 16 / 32 / 48 三个代表档,避免 DOM 里挂太多 canvas;实际生成时按所选档位逐档新建用完即弃的离屏 canvas。
常见问题
生成的 ico 文件双击打不开,提示图标损坏?
多半是 imageOffset 算错。ICO 里每一档数据的位置是绝对偏移,前面档的字节数必须逐档累加进下一档的偏移;差1 字节整个文件就废了。另一个常见原因是忘了 bytesInRes 也要用小端序写——本工具用 DataView.setUint32(..., true) 显式指定小端,避免这个问题。下载后可以先看体积对不对:3 档应该在 600 字节上下。
为什么 favicon.ico 里面能放 PNG,不是规定只能是 BMP 吗?
早期确实只有 BMP。Windows Vista 起支持在 ICO 容器里直接内嵌 PNG 负载,本工具走的就是这条路,实测 32 px 圆环图标 180 字节,而同样尺寸的未压缩 BMP 要 4264 字节。代价是极老的系统(XP 及更早)可能不认,这种场景可以改用 BMP 负载,只是体积会涨二十倍以上。
我已经放了 /favicon.ico,浏览器还是不显示?
按可能性排查:① 文件没放在站点根目录,放在 /assets/ 下不会被自动请求;② link rel="icon" 的 href 路径写错或返回 404;③ 浏览器缓存了旧图标,DevTools 里勾 Network 面板的 Disable cache 再强刷;④ 页面上有第二个 link rel="icon" 覆盖了先前的声明。本工具生成的代码块用的是根目录相对路径,符合浏览器自动探测规则。
apple-touch-icon 和 favicon.ico 需要做两份吗?
需要,它们是两回事。favicon.ico 服务桌面浏览器,apple-touch-icon 服务 iOS 添加到主屏——iOS 不读 ico,而且会自己给图标加圆角并压在一块不透明的底板上,所以 180 × 180 的PNG 要用方形原图(不带透明、不带圆角)。iOS 6 之前用 apple-touch-icon-precomposed,现在写 apple-touch-icon 即可。本页输出的是不带透明底的主色方块,正好符合 iOS 的要求。
同一个图标要做 PWA manifest,还需要哪些尺寸?
Android Chrome 会读 manifest.json 里的 icons,常见组合是 192 × 192 与 512 × 512。注意 192 不是 2 的幂(192 = 64 × 3),512 是(2^9),规范上不禁止但也不是刻意选它。如果标了 "purpose": "any maskable",图标要能承受圆形裁切——安全区是中心 80% 直径,也就是四周各内缩 10%,512 px 图就是内缩 51 px。本页当前只出 ico 档位,manifest 里先引用已生成的尺寸。
16 px 太小看不清汉字,换成字母行不行?
行,而且更推荐。16 × 16 = 256 个像素,画汉字时笔画密度太高,示例里「柳」字在 16 px 下基本认不出形状;换成 N、柳 的拼音首字母或一个 emoji 就清晰得多。这不是渲染 bug,而是信息量超过了 16 px 画布的承载能力——真要放复杂的汉字标志,最低从 32 px 起步。
前景色和背景色我随手填成一样的,图标看不见?
那是对的:对比度 1:1,图形与底色融为一体。工具不会拦你(不排除合法但难看的输入),但会在提示区告诉你对比度是 1:1。WCAG 建议正文对比度至少 4.5:1,图标这类非文字元素建议 3:1;示例的 #2563eb 与 #ffffff 约 5.17:1,16 px 下也能分辨。
下载的 ico 能不能直接改图标名?
可以,文件名无所谓,link 标签里的 href 指到哪都行。唯一有约定俗成的是根目录的 /favicon.ico:浏览器在页面没声明任何 link rel="icon" 时会自动去请求这个路径,所以很多站点干脆只放文件不写标签。命名成别的名字时,就必须确保 link 标签在,否则浏览器找不到。