左栏组件

个人名片

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
profile:
enable: true
avatar: /images/avatar.jpg
avatar_size: 72px
name: Echo
title: 万物之时
title_icon: /favicon.png
badge: LV.5
badge_title: 潜水爱好者
bio: 分享影视、游戏与各类资源,也折腾博客和 Mod 汉化。
social_title: 找到我
icon_size: 19
social:
- name: github
url: https://github.com/
title: GitHub
- name: bilibili
url: https://space.bilibili.com/
title: 哔哩哔哩
- name: telegram
url: https://t.me/
title: Telegram
- name: mail
url: mailto:[email protected]
title: 邮箱
- name: rss
url: /atom.xml
title: RSS

外观类配置项

配置项 说明 默认值
avatar 头像图片路径 主题自带占位头像
avatar_size 头像直径,接受 72px 这类带单位值,或直接写数字 72(按 px 处理) 64px
title 头像下方的主标题(如昵称、站名) 空
title_icon 主标题左侧的小图标,常配站点 favicon 使用 空
badge 头像右下角角标文字 不显示
badge_title 角标的鼠标悬停提示 空
bio 简介文字;写成 bio: false 或留空可整段隐藏 取站点 description
social_title 社交图标区上方的小标题 空
icon_size 社交图标直径(数字,按 px 处理) 19

社交链接

  • social[].name 决定图标,可用:github / bilibili / telegram / mail / rss / link。
  • social[].title 同时作为图标的 title 与无障碍标签,鼠标悬停可见。
  • avatar 加载失败时会自动回退到主题自带的占位头像。
  • 不写 name 和 bio 时,会回退到站点 _config.yml 的 author 和 description。
  • 想省掉社交区,直接把 social 整体注释掉即可,标题和分隔线会一并隐藏。

头像与角标尺寸用的是 CSS 变量(--avatar-size / --icon-size)实现,因此改动后无需改动任何样式文件。

音乐播放器

单曲模式:

1
2
3
4
5
6
7
music:
enable: true
title: 音乐
src: 'https://example.com/song.mp3'
name: 曲目名
artist: 艺术家
cover: /images/covers/hexo-theme.svg

歌单模式(填了 playlist 就优先用它):

1
2
3
4
5
6
7
8
9
10
music:
enable: true
playlist:
- name: 曲目一
artist: 歌手
src: https://example.com/a.mp3
cover: /images/covers/hexo-theme.svg
- name: 曲目二
artist: 歌手
src: https://example.com/b.mp3

播放器支持播放/暂停、上一首、下一首、随机、循环和音量。

浏览器通常禁止自动播放,需要访客手动点一次播放键。
src 必须是直链(以 .mp3 / .m4a 结尾),网盘分享页不能直接播放。

分类与标签

1
2
3
4
5
6
7
8
9
category:
enable: true
title: 分类
limit: 8 # 最多显示几个,0 表示不限

tags:
enable: true
title: 标签
limit: 16

显示顺序按内容数量从多到少,数量为 0 的分类不会出现。

左栏分类是跟随页面上下文的:

  • 首页、归档页:显示全部分类;
  • 文章页(文章总页、文章详情页、文章分类页):只显示含有文章的分类;
  • 资源页(资源总页、类型页、资源详情页):只显示含有资源帖的分类。

这样文章读者不会被资源分类干扰,资源访客也看不到纯文章分类,两侧列表都更短、更聚焦。

右栏组件

站点统计

1
2
3
4
5
6
7
8
9
10
11
stats:
enable: true
title: 统计
show:
- posts # 文章数
- categories # 分类数
- tags # 标签数
- words # 总字数
- runtime # 运行时长
- updated # 最后活动
since: 2024-01-01

show 数组控制显示哪些行以及顺序,删掉哪一项就不显示哪一项。
运行时长从 since 开始计算。

日历

1
2
3
calendar:
enable: true
title: 日历

日历支持翻月,当天有描边标记,有文章的日期会显示小圆点,
下方列出最近更新的 3 篇内容。

站点信息

1
2
3
4
5
6
7
siteinfo:
enable: true
title: 站点信息
build: Hexo
version: Echo 1.0
license: CC BY-NC-SA 4.0
domain: '' # 留空则使用站点 url

页脚

1
2
3
4
5
6
7
footer:
since: 2024
powered: true
beian:
enable: false
text: 粤ICP备00000000号
link: https://beian.miit.gov.cn/

页脚会显示 © 2024 - 2026 这样的年份区间,起始年份取 since。
开了 beian 之后会额外显示一条备案链接。

接入评论

主题内置 Giscus(基于 GitHub Discussions),在 _config.yml 里填好参数即可:

1
2
3
4
5
6
7
8
9
comments:
enable: true
provider: giscus
giscus:
repo: 用户名/仓库名
repo_id: R_kgDOxxxxxx
category: Announcements
category_id: DIC_kwDOxxxxxx
mapping: url # 用页面 URL 关联 discussion

前置条件:目标仓库必须是 public,并已安装 giscus 应用、开启 Discussions。

  • 评论框在正文上方(input_position: top),深浅色跟随站点主题切换。
  • 换成 Waline / Twikoo 等其它服务:改 layout/_partial/comments.ejs 里的脚本即可,
    文章页的引入位置不用动。

入场动画

卡片滚动进入视口时会淡入上移,由 echo.js 里的 IntersectionObserver 实现,默认开启。
想关掉的话,删除 source/js/echo.js 中「Reveal on scroll」那一段即可。

常见问题

菜单点了打不开 / 页面空白

先看终端有没有报错。最常见的原因是模板里引用了不存在的变量,
或者生成器返回的 page.posts 被当成了 Query 对象处理。

1
npx hexo clean && npx hexo generate

重新生成时终端会直接指出出错的文件和行号。

改了配置不生效

分三种情况:

改了什么 需要做什么
themes/echo/_config.yml 重启 hexo server
站点 _config.yml 重启 hexo server
scripts/*.js(生成器) 重启 hexo server
CSS / JS / 模板 一般热更新,必要时强刷(Ctrl+F5)

改了 colors.accent 却没变?主色是在 head.ejs 里注入的,
如果你改的是编译后的 public/css/echo.css,下次生成会被覆盖——
要改就改 themes/echo/_config.yml,然后 hexo clean && hexo generate。

浅色主题下横幅还是原来的深色 / 灰色

自己写浅色覆盖规则时,最容易踩的两个坑:

  1. 选择器优先级不够。主题里深色状态的横幅用的是
    .page-banner.has-banner .page-banner-card(三个 class),
    而 [data-theme='light'] .page-banner-card(一个属性 + 一个 class)压不过它。
    写浅色规则时必须带上 .page-banner / .has-banner 上下文,把优先级提上去。
  2. 横幅大图写在 HTML 内联样式里。.page-banner 的
    style="background-image:url(...)" 是模板输出的内联属性,
    普通 CSS 盖不住,需要在浅色规则里用 background: ... !important 压制。

另外浅色规则要同时照顾两个属性:data-theme(head.ejs 里的运行时 JS 写入)
和 data-theme-hint(layout.ejs 直接输出的配置值,用于 JS 尚未执行时防闪帧)。

验证时如果无头浏览器也跟着系统深色渲染,可以临时做一个强制
data-theme="light" 的验证页截图确认,改完记得删掉。

排查口诀:改完 CSS → hexo clean && hexo generate → 停掉旧 server 换端口重启 → 浏览器强刷。
只改源文件就断定”没生效”是最常见的原因,因为运行中的 server 会一直供旧 CSS。

窄屏展开菜单后白底白字(浅色主题)

如果你是照着上一条 FAQ 给自己写浅色规则时遇到的,八成是踩了同一个坑:
首页 Hero 的导航是透明悬浮在深色大图上的,所以浅色规则会主动排除它
(:not(.has-hero)),让白字保留。可是窄屏展开的抽屉菜单是
自带实底浮层(background: var(--bg-elev),浅色下为纯白),
它的链接同样继承了白字 —— 于是白底白字。

判断原则:看这个元素自己有没有底色。

  • 有自己的实底(抽屉、卡片、弹窗)→ 文字必须跟随主题色,用 var(--text) / var(--text-soft)
  • 透明悬浮在大图上(首页顶栏)→ 固定用白字,任何主题都一样

主题里对应的修法(≤900px 生效):

1
2
3
@media (max-width: 900px) {
[data-theme='light'] .site-nav .nav-link { color: #1e293b; }
}

抽屉在深色主题下本来就是深底白字,所以这条只需要覆盖浅色。

资源没出现在资源库

按顺序检查:

  1. front-matter 里 resource.enable 是不是 true
  2. resource.type 的值是否与站点 _config.yml 里 resources.types[].key 一致
  3. 文章文件是否放在 source/_posts/ 下
  4. 有没有执行过 hexo clean

侧栏收起后目录不见了

这是预期行为:右栏在 1280px 以下会收起,
此时目录会转移到正文顶部的可折叠区块,不会丢失。

封面图不显示

  • 确认路径以 / 开头,且文件真实存在于 source/images/ 下。
  • 路径是相对站点 source,不是相对文章文件。
  • 没有封面时卡片会显示渐变占位块,属于正常回退。

导航栏挡住锚点

主题已通过 scroll-padding-top 处理锚点偏移,
滚动到标题时不会贴在导航栏下面。如果你自定义了导航高度,
记得同步调整 --header-h 变量。

进阶定制

改配色

主题所有颜色都走 CSS 变量,定义在 echo.css 顶部的 :root:

1
2
3
4
5
6
7
8
9
10
11
12
:root {
--accent: #5b8cff;
--bg: #f6f7fb;
--bg-elev: #ffffff;
--text: #1b1f2a;
--border: #e4e7f0;
}
[data-theme='dark'] {
--bg: #0f1117;
--bg-elev: #171a23;
--text: #e8eaf1;
}

深色模式只需覆盖 [data-theme='dark'] 里的同名变量。

加一个侧栏组件

  1. 在 layout/_rail/ 下新建 your-widget.ejs
  2. 在 layout/_partial/rail-left.ejs 或 rail-right.ejs 里引入
  3. 在主题 _config.yml 里加对应的 enable 开关

组件外层用 rail-card 类就能自动继承卡片样式:

1
2
3
4
<section class="rail-card">
<h3 class="rail-card-title"><%- echo_icon('box', 16) %> 标题</h3>
<p>内容</p>
</section>

发布主题前要清理什么

  • 主题 _config.yml 里的个人信息、头像、社交链接
  • source/images/ 下你自己上传的图片
  • 演示文章(source/_posts/ 里的示例内容)
  • public/ 与 .deploy_git/ 之类的构建产物

想改某个字段的中文名 / 显示逻辑

资源字段(版本 / 平台 / 大小 / 语言 / 更新日期)的映射与过滤统一在
scripts/helper.js:

1
2
const RESOURCE_FIELD_LABELS = { version: '版本', platform: '平台', /* ... */ };
hexo.extend.helper.register('echo_resource_fields', function (extra) { /* ... */ });

改这里会同时影响资源卡片、资源详情页摘要、普通文章卡片三处,不用逐个模板改。
其他 helper 也都集中在同一个文件底部注册,模板里通过 echo_xxx 调用。

主题代码里哪些是「公开 API」,改动需谨慎

位置 作用 稳定性
helper.js 的 echo_* helper 模板可调用的函数 稳定,改动会影响所有模板
source/css/echo.css 的 --* 变量 主题对外暴露的设计变量 稳定,自定义 CSS 建议只改这些
.rail-card / .field-chip / .btn 等类 供你在 Markdown 里直接用的组件类 稳定,可放心在正文里用
scripts/articles.js 等生成器 改站点数据来源 内部实现,改动需同步生成器逻辑

反过来,下面这些不要依赖:

  • 纯为视觉服务的状态类(has-hero / is-scrolled / is-compact 等),
    它们会随主题实现调整
  • .ab-*(卡片网格)、.hd-*(下载区)这类给 Markdown 手写内容用的组件类,
    虽然保留但版式可能微调

系列总结

六篇下来,你应该已经掌握:

  1. 主题的架构与目录职责
  2. 安装启用与两套配置文件的区别
  3. 三栏布局、响应式收栏与首页大图
  4. 资源帖写法、网盘链接与配色
  5. 写作规范、代码块与文章页开关
  6. 侧栏组件、页脚与问题排查

后续计划:资源排序与筛选增强、磁力链接支持、评论系统开箱接入。