简介:Bootstrap Icons 1.11.3 图标库压缩包面向网页设计、前端开发与 UI 设计人员,提供一套可直接用于 Bootstrap 项目、也可独立引入的开源矢量图标资源,适合后台管理、企业官网、移动端页面等场景补齐通用界面符号。包内共 2000 个文件,其中 1994 个 SVG 图标覆盖箭头、表单、标签、社交媒体与品牌标志等常用类别,另含配套 CSS 样式、woff 与 woff2 字体、SCSS 源码及 JSON 清单,压缩包约 1.58MB,体积轻便,分类与命名便于检索。图标采用 SVG 矢量格式,缩放清晰不易失真,可通过 HTML 类名或直接引用文件调用,并能与 Vue、React、Angular 等前端框架及构建工具配合使用。读者可据此快速定位所需图标、复制矢量文件或复用样式类,统一页面视觉语言,减少额外图片与字体依赖,也可查阅 SCSS 与 JSON 清单完成批量维护。已有 440 人学习下载。
1. 本地包里到底装了什么:从一次断网事故说起
去年给某公司做内网演示,会前一天晚上页面还好好的,第二天进了隔离网段,整站图标全变成方块,按钮只剩一坨文字。查了半天不是代码问题——图标走的是外链 CSS,网断了就什么都没了。回来之后我把 bootstrap-icons-1.11.3.zip 拖进仓库的 vendor 目录,从此图标这块再没出过事。
这个包本质上是两千多个图标的两种交付形态:一套图标字体(woff2/woff + 类名 CSS),一套独立的 SVG 源文件。它能解决的核心问题很朴素——让界面里那些箭头、勾、叉、齿轮有个统一来源,不用东拼西凑找图,也不用为了三个图标引一整个图标库的运行时。适合谁?做后台管理系统、内部工具、文档站的前端,尤其是需要离线部署或者对首屏体积敏感的项目。不适合谁?需要多色插画、需要复杂路径动画的场景,那得去用 SVG 源文件自己改,字体这条路走不通。
2. 解包与三条接入路线:字体、sprite、单文件内联
拿到压缩包别急着往项目里一扔就完事。这个包里同时塞了字体方案和 SVG 方案,两套东西的文件路径、依赖关系、失效场景都不一样,先花十分钟认清楚,后面能省掉一堆"图标怎么是方块"的排查。
2.1 解包后先认清每个文件的职责
我习惯先建一个干净的 vendor 目录再解压,避免文件散落在项目根上:
# 建目录、解压、看层级 mkdir -p vendor/bootstrap-icons unzip bootstrap-icons-1.11.3.zip -d vendor/bootstrap-icons find vendor/bootstrap-icons -maxdepth 2 -type d解压完你先看到的是顶层目录,里面通常还有一个同名子目录,真正的资源在第二层。find这条命令就是为了确认层级——很多人直接-d vendor/解压,结果 CSS 里的相对路径全断,页面上图标一个都不显示,还以为是字体文件坏了。
把里面的文件按职责归一下类,心里就有数了:
| 路径 | 作用 | 什么场景该用它 |
|---|---|---|
bootstrap-icons.css | 全量类名定义 +@font-face,未压缩 | 本地调试、需要读源码 |
bootstrap-icons.min.css | 同上,压缩版 | 生产环境外链 |
font/bootstrap-icons.css | 字体方案样式,相对路径指向同级的fonts/ | 字体和样式要放一起时 |
font/fonts/*.woff2 | 主字体文件 | 现代浏览器,优先加载这个 |
font/fonts/*.woff | 回退字体 | 老环境兜底 |
icons/*.svg | 单个图标的 SVG 源文件 | 按需取用、改色、改线宽 |
icons.svg | 打包好的 sprite | 想一次引一批、又不想装字体 |
font/bootstrap-icons.json | 图标名与字符码点的映射表 | 生成子集、做图标检索、升级比对 |
这里有个容易忽略的点:bootstrap-icons.json不是给运行时用的,它是构建期的"账本"。你在做图标选择器、做按需裁剪、做版本升级核对时,全靠这张表对齐名字和码点。后面第 4 章和第 6 章都要用到它。
2.2 字体方案:一个 link 解决九成场景
绝大多数项目用字体方案就够了。它的原理很直接——每个图标在 CSS 里被定义成一个::before伪元素的字符内容,字体文件里对应的码位画的就是那个图形。所以你写<i class="bi bi-alarm"></i>,浏览器其实是渲染了一个"特殊字符",只是这个字符长得像个闹钟。
接入分两步。第一步把样式引进来:
<!-- 放在 head 里,路径按你实际的 vendor 目录改 --> <link rel="stylesheet" href="/vendor/bootstrap-icons/bootstrap-icons.css">第二步直接用类名,类名规则是固定前缀bi加图标名,两个类缺一不可:
<!-- 正确:bi 是基础类,bi-alarm 是具体图标 --> <i class="bi bi-alarm"></i> <span class="bi bi-check-circle"></span> <button type="button" class="btn"> <i class="bi bi-search" aria-hidden="true"></i> 搜索 </button>bi这个基础类不能省。它干的事是设置font-family、display、line-height和vertical-align这一套基础样式。只写bi-alarm而漏掉bi,图标会退化成一个方框或者一个乱码字符——这是最高频的翻车点,我在别人的代码里见过不止一次。标签用<i>还是<span>无所谓,语义上都只是个装饰容器,关键是那两个类。
路径这块要留个心眼。bootstrap-icons.css里的@font-face有个src,指向字体文件的位置。如果你把 CSS 单独抽出来放到/assets/css/下,字体却还在/vendor/bootstrap-icons/里,那src的相对路径就失效了,控制台会报字体 404,页面上一片方块。稳妥做法是保留font/目录的原始结构,只移动整个目录,不动内部相对关系。
字体方案的好处是省事:改大小改font-size,改颜色改color,跟调文字一模一样,不用管fill也不用管stroke。代价是每个图标只能单色,而且它是"文字",会被文本相关的样式影响——行高、字重、文本渲染模式都会作用到它身上。
2.3 SVG 路线:什么时候该放弃字体
一旦出现下面这几种需求,字体方案就到头了,该转 SVG:需要两种以上颜色(比如带底色的状态徽标)、需要单独调整某条路径的线宽、需要给图标加过渡动画、需要在打印样式里保证一定渲染出来。
最省事的 SVG 用法是直接引 sprite:
<!-- icons.svg 里的 symbol 通过 id 引用 --> <svg class="icon" width="16" height="16" aria-hidden="true"> <use href="/vendor/bootstrap-icons/icons.svg#alarm"></use> </svg><use href>里#后面跟的是 symbol 的 id。这个写法的坑在于:如果你用构建工具把 SVG 当模块处理,某些配置会把 id 重写或去掉,结果就是<use>找不到目标,页面上什么都没有,控制台也不报错——这是典型的黑匣子问题,只能靠人眼看 DOM 结构去查。
单文件内联适合图标数量极少(五个以内)的情况,直接把icons/目录下的 SVG 源码复制进组件:
<!-- 直接内联,颜色由 fill 决定,可以随意改 --> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="#d9534f" viewBox="0 0 16 16"> <path d="..."/> </svg>内联的好处是零请求、零依赖、能单独控制每一个属性;坏处是没法缓存、代码体积涨得快、图标一多模板就变得很难读。我的分界线是:同一页面用到超过十个图标,就走 sprite;只有三五个高频图标,内联反而更划算。
三条路线的选择,本质上是在"体积""灵活性""维护成本"三角里选两个。内部工具、后台页面,字体方案 + 少量内联兜底,是我用得最多的组合。
3. 尺寸、颜色与对齐:三个真正影响观感的参数
图标能显示只是及格线,要对齐、要跟文字一个视觉重量、要在不同字号下都不糊,靠的是参数调校。这一章讲的都是具体数值,不涉及原理推导,遇到观感问题直接对照改。
3.1 尺寸只认两套开关,别混用
字体图标和 SVG 图标的尺寸控制完全是两套逻辑,混用就会出现"改了没反应"。
字体图标(.bi)的尺寸由font-size决定,因为它本质是文字:
/* 字体图标:font-size 是唯一入口 */ .icon-sm { font-size: 0.875rem; } /* 14px 基准下 */ .icon-md { font-size: 1rem; } .icon-lg { font-size: 1.5rem; } /* 注意:给 .bi 设 width/height 在字体方案下是无效的 */SVG 图标(<svg>或<use>)反过来,由width/height属性或者 CSS 的宽高决定,font-size对它没有直接作用(除非你用了em单位间接继承):
/* SVG 图标:宽高 + viewBox 决定缩放 */ .icon { width: 1em; height: 1em; fill: currentColor; }为什么推荐 SVG 用1em?因为这样它会自动跟随父元素的字号缩放,图标和文字的相对大小关系在任何字号下都保持一致,不用为每个断点单独写一套尺寸。这是我踩过坑之后固定下来的写法——早些年用固定px,结果移动端把根字号调小,文字变小了图标没变,一排按钮里图标全显得偏大。
参数上的经验值:正文文字14px时,图标用1em就是14px,视觉上略小,通常在1.05em到1.15em之间微调最舒服,具体取决于图标本身的留白。有些图标(比如带外框的方形图标)自带的留白多,同样的1em看起来就比线条图标小一圈,这时候不能统一改,得给那一类单独加个类。
3.2 颜色跟着 currentColor 走,多色得另起炉灶
字体图标的颜色天然继承color,这个没什么好调的。SVG 图标要拿到同样的效果,必须保证源文件的路径上写的是fill="currentColor",而不是写死的#000。
/* 让 SVG 图标跟随文字颜色 */ .icon { fill: currentColor; color: inherit; } /* 语义色:父级给颜色,图标自动跟随 */ .status-ok { color: #198754; } .status-warn { color: #ffc107; } .status-error { color: #dc3545; }<!-- 图标颜色由父级 class 决定,不用单独给 SVG 设 fill --> <span class="status-ok"><svg class="icon"><use href="#check"></use></svg> 已完成</span>这里有个边界要说清楚:currentColor只能给一个颜色。如果你的图标需要两个颜色——比如一个带填充背景的圆加一个白色的勾——字体方案和无脑currentColor都做不到,必须回到单文件 SVG,把两条路径分别设fill。这时候就该老老实实内联,别硬用<use>,因为<use>引用的 symbol 内部样式是封闭的,外部 CSS 很难精准改到某一条路径。
还有一个隐蔽的坑:如果你在 SVG 源文件上设了fill="currentColor",同时又在 CSS 里写了fill: #333,CSS 的优先级更高,currentColor就失效了,图标永远是深灰。表现是"改父级颜色图标不变",很多人查到半夜。我的习惯是 SVG 图标只写一处颜色来源,要么全交给 CSS,要么全写在属性上。
3.3 垂直对齐与基线漂移
这是最容易被忽略但观感影响最大的一项。字体图标本质是字符,它坐在文本基线上,而字符的字形高度和实际矩形边界往往不重合,结果就是图标比文字高一点或者低一点,一排按钮里看着像没对齐。
/* 基础类里通常已经带了这一句,自己覆写时别丢掉 */ .bi { display: inline-block; vertical-align: -0.125em; line-height: 1; }vertical-align: -0.125em的意思是往下挪一点,让图标的视觉中心跟文字的小写字母中心对齐。这个值不是固定的——如果你把图标用在纯大写的按钮里,或者用在line-height很大的容器里,-0.125em可能就不够了。判断方法很简单:拿一个"口"字和一个图标并排放,眯眼看它们的重心是不是在同一条水平线上。
调试的时候我会临时加个背景色:
/* 临时调试用,确认对齐后删掉 */ .bi, .icon { background: rgba(255, 0, 0, 0.15); }红色块能直接暴露图标的实际占位范围和基线位置,比盯着像素猜快得多。这个习惯帮我省过好几次"为什么就是差一像素"的纠结。
还有一个跟对齐相关的问题:line-height会撑高图标所在的容器。图标本身line-height: 1,但如果它的父级是line-height: 1.8的段落,整个段落的高度不会变,图标却被垂直居中了。想让图标跟文字严格贴合,父级要么给line-height: 1,要么给图标加display: inline-flex; align-items: center;,把对齐从基线模式换成 flex 模式。
4. 按需裁剪:把全量包压到只留自己用到的图标
全量字体文件体积不小,对一个只用三十个图标的后台来说,把两千多个字形全下下来是浪费。这一章讲的是怎么把全量包裁成一个精简版,以及为什么我建议把这套流程固化成脚本而不是手工复制。
4.1 先盘点:到底哪些图标真的在用
裁剪的前提是知道用了什么。别凭印象列清单,直接扫代码:
# 从模板、组件、脚本里扫出所有 bi-xxx 类名,去重计数 grep -rhoE 'bi-[a-z0-9-]+' src/ \ | grep -v '^bi-$' \ | sort | uniq -c | sort -rn > /tmp/icon-usage.txt # 看一眼前 20 个高频图标 head -20 /tmp/icon-usage.txt # 总数量 wc -l < /tmp/icon-usage.txt-r递归、-h不显示文件名、-o只输出匹配部分,这三个参数组合起来能把所有类名抽出来。uniq -c统计频次,方便你判断哪些是核心图标、哪些只在一处用过。这份清单要留档,后面升级版本时拿它当基线。
扫出来的结果会有"脏数据":注释里写过的类名、已经删掉的组件残留、字符串拼接出来的动态类名(比如'bi-' + type)。动态拼接的类名扫不到,这是这个方法的固有盲区。我的应对是在代码里加一行显式声明,把可能动态生成的图标名集中写在一个常量文件里,扫描时把这个文件也纳入范围。
4.2 用脚本生成子集 sprite
有了清单,就可以从icons/目录里挑出对应的 SVG,拼成一个精简的 sprite。我一般写成 Python 脚本放进构建流程,而不是手工复制粘贴——手工做过一次就知道,漏一个图标导致线上空白,排查成本远高于写这五十行脚本。
#!/usr/bin/env python3 """从全量图标包生成项目自用的 SVG sprite""" import re from pathlib import Path ICON_DIR = Path("vendor/bootstrap-icons/icons") OUT_FILE = Path("dist/icons-sprite.svg") # 从 4.1 的扫描结果里整理出的白名单,放单独文件便于维护 WANTED = [line.split()[-1].replace("bi-", "", 1) for line in Path("config/icons.txt").read_text().splitlines() if line.strip()] parts = ['<svg xmlns="http://www.w3.org/2000/svg" style="display:none">'] missing = [] for name in sorted(set(WANTED)): src = ICON_DIR / f"{name}.svg" if not src.exists(): missing.append(name) # 名字写错或版本里没有,单独收集 continue raw = src.read_text(encoding="utf-8") # 从源文件里读 viewBox,不要硬编码,不同图标可能不一致 m = re.search(r'viewBox="([^"]+)"', raw) viewbox = m.group(1) if m else "0 0 16 16" # 剥掉外层 <svg ...>,只留内部路径 inner = re.sub(r"^.*?<svg[^>]*>", "", raw, flags=re.S) inner = re.sub(r"</svg>\s*$", "", inner, flags=re.S).strip() parts.append(f'<symbol id="i-{name}" viewBox="{viewbox}">{inner}</symbol>') parts.append("</svg>") OUT_FILE.parent.mkdir(parents=True, exist_ok=True) OUT_FILE.write_text("\n".join(parts), encoding="utf-8") print(f"生成 {len(parts) - 2} 个 symbol,输出 {OUT_FILE.stat().st_size} 字节") if missing: print("以下图标未找到,检查名字拼写:", missing)几处关键逻辑值得单独说。viewBox从源文件里正则提取而不是写死,是因为图标集内部偶尔有非标准尺寸的图形,硬编码会导致某些图标被裁掉一截。missing列表必须有——白名单里出现一个不存在的名字,如果脚本静默跳过,你只会看到页面上少了个图标,不会知道是哪一步出的问题。style="display:none"挂在根<svg>上,是为了让 sprite 本身不占位,同时打散到symbol里的图形不会在页面上显示出来。
跑完之后在页面顶层引一次 sprite,然后任何地方都能用<use href="#i-xxx">引用。这套流程在编译器里跑,图标增删改都走白名单,比手动维护字体文件可靠得多。
如果项目确实需要字体方案(比如老环境不支持<use>),也可以用字体打包工具把这份白名单生成一个精简的 woff2,思路一样:只打包用到的字形。体积收益更明显,但改图标的流程会重一点。
4.3 封装成组件,别在业务代码里裸写类名
裁剪做得再好,如果业务代码里到处是<i class="bi bi-xxx">,下次换图标方案就是一场灾难。我的做法是封一层薄组件,让业务只关心语义名,不关心底层是字体还是 SVG。
// Icon.jsx —— 只暴露 name 和 size,内部实现随时可换 const ICONS = { search: "i-search", check: "i-check-circle", close: "i-x-lg", }; export function Icon({ name, size = "1em", className = "", ...rest }) { const symbolId = ICONS[name]; if (!symbolId) { // 名字不在白名单里,开发期直接抛错,别让它在线上变成空白 if (process.env.NODE_ENV !== "production") { throw new Error(`未登记的图标: ${name}`); } return null; } return ( <svg className={`icon ${className}`} width={size} height={size} aria-hidden="true" focusable="false" {...rest} > <use href={`#${symbolId}`} /> </svg> ); }这个组件干了三件事:把字符串名映射成 symbol id、给未知图标在开发期抛错、默认带上aria-hidden和focusable="false"。第三条是无障碍的基本要求——装饰性图标不能被读屏软件念出来,也不能进 Tab 焦点链,否则键盘用户每经过一个图标就要停一次。如果图标是唯一的表意元素(比如只有一个叉的关闭按钮),那就不能aria-hidden,得给它配aria-label或者用可访问文字。
组件化之后,白名单和组件里的ICONS映射还能互相校验:构建脚本比对两边,对不上就报错。这套机制建立起来之后,换图标库这种事从"重写三个月"变成"改一个映射表"。
5. 排查手册:五个反复出现的现象
以下五条都是我或者同事真实撞过的,按现象、原因、解决三段来写,遇到问题直接对号入座。
5.1 图标显示成方块或问号
现象:页面加载正常,CSS 也加载了,但图标位置显示成方块、问号或者一个带数字的六边形。
原因:九成是字体文件没加载成功。要么路径错了(构建工具把 CSS 抽到别处,相对路径失效),要么服务端没有给.woff2配正确的 MIME 类型,要么跨域被拦了。开发环境还有一种可能:字体文件在,但 CSS 里的@font-face的font-family名字跟.bi类里写的不一致。
解决:打开网络面板筛 "font",看有没有 404 或 403。有 404 就顺着 CSS 里的url()路径核对实际文件位置;有 200 但图标还是方块,就在控制台执行getComputedStyle(document.querySelector('.bi')).fontFamily,看实际生效的字体族是什么,跟@font-face声明的对不对得上。服务端记得给.woff2加font/woff2,.woff加font/woff。
5.2 升级后部分图标变成空白
现象:把包从旧版本换到 1.11.3,大部分图标正常,少数几个位置空着,DOM 里节点还在但没有任何内容。
原因:图标集在版本迭代里会改名或者合并。旧名字在新版本里可能被拆成两个、也可能被重命名成更语义化的名字。改名的图标在新 CSS 里没有对应的类名定义,::before的content为空,于是渲染出一个零宽字符。
解决:拿新旧两份bootstrap-icons.json做差集,把被删掉的名字全部列出来,逐个映射到新名字。第 6 章给了具体脚本。这个坑我吃过一次,当时是升级到新版本之后有四个图标凭空消失,查了两个小时才发现是改名。
5.3 首屏图标闪一下才出现
现象:字体加载的那几百毫秒里,图标位置先显示成方块或者空白,字体到位后才变成图形,肉眼能看到一次闪烁。
原因:浏览器的字体加载策略默认有一段时间的"阻塞期",阻塞期结束后如果字体还没到,就先渲染回退字形,等字体到了再替换,这个替换过程就是闪烁。
解决:给@font-face加font-display: swap,让回退字形立刻可见(虽然还是方块,但不会白屏);更彻底的做法是预加载字体文件:
<!-- 放在 head 里靠前的位置,和样式表并列 --> <link rel="preload" href="/vendor/bootstrap-icons/font/fonts/bootstrap-icons.woff2" as="font" type="font/woff2" crossorigin>crossorigin不能省,字体请求属于跨源请求,缺了这个属性预加载会失败,控制台会有一条警告,但页面看起来正常,很容易被忽略。如果连这一下闪烁都不能接受,那就是该换 SVG sprite 的信号了——SVG 内联在 HTML 里,不存在异步加载。
5.4 打印预览里图标全没了
现象:屏幕上看得好好的,一按打印预览,所有图标消失,只留下空白。
原因:浏览器打印时默认不加载网络字体,尤其是用户没勾"打印背景图形"的时候。字体图标依赖字体文件,字体没加载自然就没图形。
解决:走 SVG 路线就没这个问题。如果必须用字体,就针对打印媒体写一套兜底样式,把关键图标换成内联 SVG 或者用文字符号顶替:
@media print { /* 打印时隐藏字体图标,用生成的文字前缀代替 */ .bi { display: none; } .print-fallback::before { content: attr(data-label); } }这个坑最坑的地方在于它上线前很难发现——没人会在开发阶段反复按 Ctrl+P。
5.5 构建产物里 CSS 路径错位
现象:本地开发一切正常,构建打包部署之后图标全变方块,本地复现不了。
原因:构建工具把 CSS 从vendor/bootstrap-icons/抽出来,合并进了dist/css/app.css,但 CSS 里的url(./fonts/xxx.woff2)是相对原位置的。新位置下这个相对路径指向了一个不存在的目录。
解决:两种思路。一是把整个font/目录原样拷进产物,保持相对结构不变;二是在构建配置里给字体文件设publicPath或者用url()重写插件把它改成绝对路径或 CDN 前缀。我一般选第一种,因为改动最小、不依赖构建工具的版本行为。验证方法很简单:构建后打开产物目录,用find dist -name "*.woff2"确认文件在,再对照 CSS 里的url()逐段核路径。
6. 版本升级核对:用 JSON 清单把改名和新增一次性对清楚
升级图标包最怕的不是新增,是悄悄改名。浏览器不会因为你写了个失效的类名就报错,它只是安静地渲染一个空字符,等到用户截图反馈"这里怎么空了一块"的时候,你早就忘了改过什么。
我现在的固定动作是:拿到新版本的bootstrap-icons.json,跟仓库里旧版本的做一次结构化比对,把三类变动全部列出来——新增、删除、码点变动。名字不变的图标码点变了,意味着字形被重画过,视觉上可能跟旁边的图标不再协调,这类也得看一眼。
#!/usr/bin/env python3 """比对两个版本的图标清单,输出升级影响面""" import json import sys from pathlib import Path def load(p): data = json.loads(Path(p).read_text(encoding="utf-8")) # 清单是 图标名 -> 码点 的映射;键统一成小写,避免大小写差异干扰比对 return {str(k).lower(): v for k, v in data.items()} old_path, new_path = sys.argv[1], sys.argv[2] old, new = load(old_path), load(new_path) added = sorted(set(new) - set(old)) removed = sorted(set(old) - set(new)) recoded = sorted(k for k in set(old) & set(new) if old[k] != new[k]) print(f"新增 {len(added)} 个:") for name in added[:20]: print(f" + {name}") print(f"\n删除 {len(removed)} 个(需要改名映射):") for name in removed: print(f" - {name}") print(f"\n码点变动 {len(recoded)} 个(字形被重画,注意视觉一致性):") for name in recoded: print(f" ~ {name}: {old[name]} -> {new[name]}")用法很简单,两个路径参数分别指旧版和新版的 JSON:
python diff_icons.py old/bootstrap-icons.json \ vendor/bootstrap-icons/font/bootstrap-icons.json拿到结果之后,重点看"删除"那一段。把每个被删掉的名字拿到新版清单里搜一搜,找语义最接近的替代(通常是加了方向后缀或者名词更具体的版本),然后写一张映射表:
// 升级映射表,配合第 4 章的组件一起用 const LEGACY_MAP = { "check-circle": "check-circle-fill", // 示例:按实际比对结果填 "x": "x-lg", };这张表的作用是让旧代码还能跑,同时给新代码指引。等一次完整的迭代周期过去,旧名字的引用清零,把映射表删掉,升级才算真正收尾。
还有一个验证环节别省:升级后把第 4.1 节扫出来的高频图标清单重新跑一遍,用新版本逐个生成 SVG 渲染到一张对照页上,肉眼过一遍。脚本能查出名字不存在,但查不出"图标还在、只是线条变细了"这种视觉变更。上面那段码点比对就是为这件事准备的——码点变了就说明字形换过,必须人工看。
说个教训。有次我图省事,直接替换了整个目录,没做比对,也没跑对照页。上线三天后有用户反馈侧边栏的折叠箭头方向反了——那个图标在新版本里被重画成了镜像版本,类名完全没变。从那以后我每次升级图标包,diff_icons.py和对照页这两步都是强制走一遍的,不管版本号只跳了一个小版本。图标这种东西,看起来最不起眼,出问题时也最难被自动化测试覆盖。希望帮到你。
本文还有配套的精品资源,点击获取