前言

Hexo Butterfly 主题默认使用 FontAwesome 图标库,虽然功能强大,但在某些场景下存在一些不足:

  • 🚫 图标种类受限:FontAwesome 的图标虽然丰富,但无法满足所有个性化需求
  • 🐌 加载速度较慢:完整的 FontAwesome 库体积较大
  • 🎨 自定义困难:无法使用自己设计的图标

而阿里云的 iconfont 矢量图标库则完美解决了这些问题:

  • ✅ 海量图标资源,支持上传自定义 SVG
  • ✅ 按需加载,只引入需要的图标
  • ✅ 完全免费,国内访问速度快

本文将详细介绍如何在 Butterfly 主题中集成 iconfont,并通过配置文件统一管理所有图标。

一、什么是 Iconfont?

Iconfont(图标字体) 是一种将图标以字体形式引入网页的技术。阿里云的 iconfont 平台提供了:

  1. 海量图标库:数百万个图标可供选择
  2. 项目管理:可以创建项目,将需要的图标添加到项目中
  3. 多种引入方式:支持 Unicode、Font class、Symbol 等多种方式
  4. 自定义上传:支持上传自己设计的 SVG 图标

为什么选择 Symbol 引用方式?

Iconfont 支持三种引用方式:

方式优点缺点
Unicode兼容性好不支持多色图标,语义不明确
Font class语义明确,使用方便不支持多色图标
Symbol支持多色图标,矢量无失真需要浏览器支持 SVG

本文采用 Symbol 引用方式,优势如下:

  • ✅ 支持多色图标
  • ✅ 通过 SVG 渲染,图标质量高
  • ✅ 可以通过 CSS 控制颜色和大小
  • ✅ 语义化程度高

二、在阿里云 Iconfont 创建项目

1. 注册并登录

访问 iconfont.cn,使用支付宝或 GitHub 账号登录。

2. 创建图标项目

  1. 点击右上角”资源管理” → “我的项目”
  2. 点击”新建项目”
  3. 填写项目信息:
    • 项目名称:如 hexo-blog-icons
    • 前缀icon-(重要!后续会用到)
    • FontClass/Symbol 前缀icon-

3. 添加图标到项目

有两种方式添加图标:

方式一:搜索并添加现有图标

  1. 在首页搜索框输入关键词,如”搜索”、”菜单”等
  2. 找到喜欢的图标,点击”加入购物车”
  3. 点击右上角购物车图标,选择”添加至项目”
  4. 选择你创建的项目

方式二:上传自定义 SVG

  1. 在项目页面点击”上传图标”
  2. 选择 SVG 文件(需要是单色或多色的矢量图)
  3. 系统会自动生成图标

4. 生成在线链接

  1. 进入你的项目页面
  2. 点击”Symbol” 标签
  3. 点击”生成代码” → “复制代码”
  4. 得到类似这样的链接:
    1
    //at.alicdn.com/t/c/font_4961003_rqnmjsg0krh.js

三、在 Butterfly 主题中引入 Iconfont

1. 在配置文件中引入 JS

编辑 _config.butterfly.yml,找到 inject 配置项:

1
2
3
4
5
6
inject:
head:
# 引入 iconfont JS 文件
- <script src="//at.alicdn.com/t/c/font_4961003_rqnmjsg0krh.js"></script>
# 添加 iconfont 样式
- '<style>.icon {width: 1.5em; height: 1.5em; vertical-align: text-bottom; fill: currentColor; overflow: hidden;}</style>'

注意事项

  • ⚠️ 每次在 iconfont 项目中添加新图标后,需要重新生成代码并更新这个链接
  • ⚠️ 建议使用 // 开头的协议相对路径,自动适配 http/https

2. 配置图标管理系统

_config.butterfly.yml 的最前面添加全局图标配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# --------------------------------------
# Global Icon Settings
# 全局图标设置
# 所有图标支持 FontAwesome 和 iconfont 两种方式
# 如果使用 iconfont,图标名称必须以 'icon-' 开头
# 如果不设置,将使用默认的 FontAwesome 图标
# --------------------------------------

icons:
# 导航栏图标
nav:
search: icon-sousuo # 搜索按钮图标
menu_toggle: fas fa-bars # 移动端菜单按钮

# 文章页面图标
post:
edit: icon-bianji # 编辑按钮
calendar: icon-rili # 发布日期
updated: icon-gengxin # 更新日期
category: icon-fenlei # 分类
separator: icon-jiantou # 分隔符
wordcount: icon-wenzi # 字数统计
readtime: icon-shijian # 阅读时间
views: icon-yulan # 浏览量
comments: icon-pinglun # 评论数
sticky: icon-zhiding # 置顶标识

# 分页图标
pagination:
prev: fas fa-chevron-left # 上一页
next: fas fa-chevron-right # 下一页

# 首页文章列表图标
index:
calendar: icon-rili # 日期
updated: icon-gengxin # 更新时间
category: icon-fenlei # 分类
category_separator: icon-jiantou # 分类分隔符
tag: icon-biaoqian # 标签
comment: icon-pinglun # 评论
sticky: icon-zhiding # 置顶

# 侧边栏卡片图标
aside:
webinfo: icon-tongji # 网站信息卡片
announcement: icon-gonggao # 公告卡片
tags: icon-biaoqian # 标签卡片
recent_post: icon-wenzhang # 最近文章卡片
newest_comment: icon-pinglun # 最新评论卡片
toc: icon-mulu # 目录卡片
post_series: icon-xilie # 文章系列卡片

# 网站信息统计图标
webinfo_item:
article_count: icon-wenzhang # 文章数量
runtime: icon-yunxing # 运行时间
total_wordcount: icon-wenzi # 总字数
site_uv: icon-yonghu # 访客数
site_pv: icon-fangwen # 访问量
last_push: icon-gengxin # 最后更新

# 版权信息图标
copyright:
author: icon-zuozhe # 作者
link: icon-lianjie # 链接
notice: icon-banquan # 版权声明

四、修改模板文件支持 Iconfont

核心思路

要让主题支持 iconfont,需要修改相应的 Pug 模板文件。核心思路是:

  1. 创建 renderIcon mixin:根据图标名称判断是 iconfont 还是 FontAwesome
  2. 从配置读取图标:从 _config.butterfly.yml 读取图标配置
  3. 条件渲染:根据前缀 icon- 判断使用哪种渲染方式

renderIcon Mixin 实现

1
2
3
4
5
6
7
8
9
10
11
//- 图标渲染混入(Mixin)
mixin renderIcon(iconClass, extraClass)
if iconClass
- const isIconfont = iconClass.startsWith('icon-')
if isIconfont
//- 渲染 iconfont(SVG)
svg.icon(class=extraClass aria-hidden="true")
use(xlink:href='#' + iconClass)
else
//- 渲染 FontAwesome
i(class=iconClass + (extraClass ? ' ' + extraClass : ''))

实战案例 1:导航栏搜索图标

文件位置themes/butterfly/layout/includes/header/nav.pug

修改前(硬编码):

1
2
3
4
#search-button
span.site-page.social-icon.search
i.fas.fa-search.fa-fw
span= ' ' + _p('search.title')

修改后(可配置):

1
2
3
4
5
6
7
8
9
10
#search-button
span.site-page.social-icon.search
- const searchIcon = theme.icons && theme.icons.nav && theme.icons.nav.search || 'fas fa-search'
- const isIconfont = searchIcon.startsWith('icon-')
if isIconfont
svg.icon.fa-fw(aria-hidden="true")
use(xlink:href='#' + searchIcon)
else
i.fa-fw(class=searchIcon)
span= ' ' + _p('search.title')

实战案例 2:文章页面图标

文件位置themes/butterfly/layout/includes/header/post-info.pug

修改要点

  1. 在文件开头定义 renderIcon mixin
  2. 从配置中读取图标:theme.icons.post.calendar
  3. 使用 mixin 渲染图标

示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//- 定义 mixin
mixin renderIcon(iconClass, extraClass)
if iconClass
- const isIconfont = iconClass.startsWith('icon-')
if isIconfont
svg.icon(class=extraClass aria-hidden="true")
use(xlink:href='#' + iconClass)
else
i(class=iconClass + (extraClass ? ' ' + extraClass : ''))

//- 使用 mixin
.post-meta-date
- const calendarIcon = theme.icons && theme.icons.post && theme.icons.post.calendar || 'far fa-calendar-alt'
+renderIcon(calendarIcon, 'post-meta-icon')
span.post-meta-label= _p('post.date')
time.post-meta-date-created= date(page.date, config.date_format)

实战案例 3:侧边栏卡片图标

文件位置themes/butterfly/layout/includes/widget/card_tags.pug

完整示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//- 图标渲染 mixin
mixin renderIcon(iconClass, extraClass)
if iconClass
- const isIconfont = iconClass.startsWith('icon-')
if isIconfont
svg.icon(class=extraClass aria-hidden="true")
use(xlink:href='#' + iconClass)
else
i(class=iconClass + (extraClass ? ' ' + extraClass : ''))

if theme.aside.card_tags.enable
.card-widget.card-tags
.item-headline
//- 从配置读取图标
- const tagsIcon = theme.icons && theme.icons.aside && theme.icons.aside.tags || 'fas fa-tags'
+renderIcon(tagsIcon, '')
span= _p('aside.card_tags')
.card-tag-cloud!=tagcloud({min_font: theme.aside.card_tags.limit ? 15 : 13, max_font: theme.aside.card_tags.limit ? 20 : 20, amount: theme.aside.card_tags.limit, color: theme.aside.card_tags.color, orderby: theme.aside.card_tags.orderby, order: theme.aside.card_tags.order})

实战案例 4:社交媒体图标

文件位置themes/butterfly/layout/includes/header/social.pug

支持颜色自定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//- 带样式的 mixin
mixin renderIcon(iconClass, extraClass, iconStyle)
if iconClass
- const isIconfont = iconClass.startsWith('icon-')
if isIconfont
svg.icon(class=extraClass aria-hidden="true" style=iconStyle)
use(xlink:href='#' + iconClass)
else
i(class=iconClass + (extraClass ? ' ' + extraClass : '') style=iconStyle)

each url, icon in theme.social
-
const [link, title, color] = url.split('||').map(i => trim(i))
const href = url_for(link)
const iconStyle = color ? `color: ${color.replace(/[\'\"]/g, '')};` : ''
const iconTitle = title || ''
a.social-icon(href=href target="_blank" title=iconTitle)
+renderIcon(icon, '', iconStyle)

配置示例

1
2
3
4
social:
icon-bilibili: https://space.bilibili.com/xxx || B站
icon-github: https://github.com/xxx || GitHub
icon-email: mailto:xxx@example.com || Email || '#4a7dbe'

五、需要修改的文件清单

根据图标位置,需要修改以下 Pug 模板文件:

1. 导航相关

  • themes/butterfly/layout/includes/header/nav.pug - 搜索、菜单按钮

2. 文章相关

  • themes/butterfly/layout/includes/header/post-info.pug - 文章元信息图标
  • themes/butterfly/layout/includes/post/post-copyright.pug - 版权信息图标

3. 首页相关

  • themes/butterfly/layout/includes/mixins/indexPostUI.pug - 首页文章列表图标

4. 侧边栏相关

  • themes/butterfly/layout/includes/widget/card_announcement.pug - 公告卡片
  • themes/butterfly/layout/includes/widget/card_tags.pug - 标签卡片
  • themes/butterfly/layout/includes/widget/card_webinfo.pug - 网站信息卡片
  • themes/butterfly/layout/includes/widget/card_recent_post.pug - 最近文章卡片
  • themes/butterfly/layout/includes/widget/card_newest_comment.pug - 最新评论卡片
  • themes/butterfly/layout/includes/widget/card_post_toc.pug - 目录卡片
  • themes/butterfly/layout/includes/widget/card_post_series.pug - 文章系列卡片
  • themes/butterfly/layout/includes/widget/card_author.pug - 作者信息卡片

5. 其他组件

  • themes/butterfly/layout/includes/pagination.pug - 分页按钮
  • themes/butterfly/layout/includes/header/social.pug - 社交媒体图标

六、实际效果展示

配置前后对比

使用 FontAwesome(默认)

1
2
3
icons:
nav:
search: fas fa-search

渲染结果:
1
<i class="fas fa-search fa-fw"></i>

使用 Iconfont

1
2
3
icons:
nav:
search: icon-sousuo

渲染结果:
1
2
3
<svg class="icon fa-fw" aria-hidden="true">
<use xlink:href="#icon-sousuo"></use>
</svg>

混合使用示例

可以在同一个配置中混合使用 FontAwesome 和 iconfont:

1
2
3
4
5
6
icons:
post:
calendar: icon-rili # 使用 iconfont
category: fas fa-folder # 使用 FontAwesome
tag: icon-biaoqian # 使用 iconfont
comment: far fa-comments # 使用 FontAwesome

七、常见问题与解决方案

Q1:图标不显示怎么办?

可能原因 1:iconfont JS 未加载

检查方法:

  1. F12 打开浏览器开发者工具
  2. 切换到 Network 标签
  3. 刷新页面,搜索 font_ 关键词
  4. 确认 JS 文件加载成功(状态码 200)

可能原因 2:图标名称错误

检查方法:

1
2
3
// 在浏览器控制台执行
Array.from(document.querySelectorAll('symbol[id^="icon-"]'))
.map(s => s.id)

这会列出所有可用的图标名称,确认你使用的名称是否存在。

可能原因 3:浏览器缓存

解决方法:

  • Ctrl + F5 强制刷新
  • 或在开发者工具中勾选 “Disable cache”

Q2:如何快速查找图标?

在 iconfont 网站:

  1. 使用中文或英文关键词搜索
  2. 可以按”下载量”、”收藏量”排序
  3. 点击图标可以预览不同尺寸效果

推荐搜索关键词:

  • 搜索:search, sousuo, 放大镜
  • 菜单:menu, caidan, 汉堡
  • 标签:tag, biaoqian, 标记
  • 时间:time, clock, rili, 日历

Q3:更新图标后不生效?

每次在 iconfont 项目中添加或修改图标后:

  1. 在 iconfont 网站点击”更新代码”
  2. 复制新的 JS 链接(注意版本号会变化)
  3. 更新 _config.butterfly.yml 中的链接
  4. 清理 Hexo 缓存
    1
    2
    3
    hexo cl
    hexo g
    hexo s

Q4:如何自定义图标样式?

themes/butterfly/source/css/custom.css 中添加:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/* 调整图标大小 */
.icon {
width: 1.2em;
height: 1.2em;
}

/* 特定位置的图标样式 */
.post-meta-icon.icon {
width: 1em;
height: 1em;
margin-right: 0.3em;
}

/* 图标悬停效果 */
.social-icon .icon {
transition: all 0.3s;
}

.social-icon:hover .icon {
transform: scale(1.2);
color: #49b1f5;
}

八、优化建议

1. 按需添加图标

不要一次性添加太多图标到项目中,只添加实际使用的图标,可以:

  • ✅ 减小 JS 文件体积
  • ✅ 加快页面加载速度
  • ✅ 方便管理和维护

2. 使用语义化的图标名称

在 iconfont 项目中给图标设置有意义的名称:

❌ 不推荐:icon-001, icon-abc
✅ 推荐:icon-search, icon-menu, icon-calendar

3. 定期更新和备份

  • 定期检查图标是否还在项目中
  • 导出项目配置进行备份
  • 记录每次更新的图标清单

4. 建立图标命名规范

建议使用统一的命名规范:

1
2
3
4
5
6
7
8
9
# 功能-对象 的命名方式
icon-search-article # 搜索文章
icon-view-count # 浏览计数
icon-tag-cloud # 标签云

# 或使用中文拼音
icon-sousuo # 搜索
icon-biaoqian # 标签
icon-fenlei # 分类

九、总结

通过本文的配置,我们实现了:

统一管理:所有图标在一个配置文件中集中管理
灵活替换:随时可以更换任何图标,无需修改代码
性能优化:按需加载,只引入使用的图标
个性化:可以使用自定义 SVG 图标
兼容性:支持 FontAwesome 和 iconfont 混用

配置流程回顾

1
2
3
4
5
6
7
8
graph LR
A[注册 iconfont] --> B[创建项目]
B --> C[添加图标]
C --> D[生成代码]
D --> E[引入到 Hexo]
E --> F[配置图标]
F --> G[修改模板]
G --> H[测试效果]

核心代码

配置文件_config.butterfly.yml):

1
2
3
4
5
6
7
inject:
head:
- <script src="//at.alicdn.com/t/c/font_xxx.js"></script>

icons:
nav:
search: icon-sousuo

模板文件(所有 .pug 文件):

1
2
3
4
5
6
7
8
mixin renderIcon(iconClass, extraClass)
if iconClass
- const isIconfont = iconClass.startsWith('icon-')
if isIconfont
svg.icon(class=extraClass aria-hidden="true")
use(xlink:href='#' + iconClass)
else
i(class=iconClass + (extraClass ? ' ' + extraClass : ''))

希望这篇文章能帮助你成功配置 iconfont,让你的博客更加个性化!如果有任何问题,欢迎在评论区讨论。

参考资源