Fluid主题の博客美化

本文最后更新于 2025年5月20日 下午

_config.yml 是本地博客项目配置文件,_config.fluid.yml 是 Fluid 主题配置文件。执行 generate 命令时,Hexo 会将配置数据渲染到 HTML 文件中。本篇仅列出一些常规设置,Fluid 配置指南 有详细的主题配置说明。

主题配置作用于主题指定的模块范围。 Fluid 主题的模块范围有【页头导航栏】、【页脚】和具体页面区域等。

如果需要修改其他区域范围,使博客更具个人色彩,可以修改源代码。

注意】:配置文件及其他程序文件要以 utf8 编码,否则涉及中文的页面会出现乱码。

Hexo博客Fluid主题魔改记录 - KEVIN’S BLOG

Hexo + Fluid 美化 | EmoryHuang’s Blog

https://mrna16.github.io/2024/11/14/【Hexo】Fluid主题美化/

1. 全局

网站 title 和图标

图标 | Hexo Fluid 用户手册

优质的10个免费icon图标网站_iconstore-CSDN博客

网站 title:修改配置文件(_config.yml)的 title 属性

1
title: shaton沙桐

网站图标:修改主题配置文件(_config.fluid.yml)的 favicon 属性

1
2
3
4
5
6
7
8
9
# _config.fluid.yml

# 用于浏览器标签的图标
# Icon for browser tab
favicon: /images/favicon/shaton.ico # 对应 source/images/favicon/shaton.ico

# 用于苹果设备的图标
# Icon for Apple touch
apple_touch_icon: /images/favicon/shaton.ico

网站图标和 title

页头导航栏:左侧的标题

1
2
3
4
# _config.fluid.yml

navbar:
blog_title: "shaton沙桐的乐色桶"

页头导航栏:menu

二级目录:Hexo在fluid主题下自定义分类导航 - 这里是后花园

暂时没这个需求。

页脚:展示 PV 与 UV 统计

PV,Page View,页面浏览量。UV,Unique Visitor,独立访客数。

Fluid 主题默认集成了 busuanzi | leancloud | umami,用于展示网站的 PV 与 UV 统计数。

暂时使用 busuanzi,不蒜子不需要申请账号,简单易用。

1
2
3
4
5
6
7
8
9
10
# _config.fluid.yml

footer:
# 展示网站的 PV、UV 统计数
statistics:
enable: true # 设置为 true,开启。
# Options: busuanzi | leancloud | umami
source: "busuanzi" #
pv_format: "总访问量 {} 次" # 显示的文本,{}是数字的占位符(必须包含),下同
uv_format: "总访客数 {} 人"

页脚:添加博客运行时间

首先,在主题配置的 footer.content 部分添加 <div> 标签,内容如下:

1
2
3
4
5
6
7
8
9
10
# _config.fluid.yml

footer:
content: '
<div>
<span id="timeDate">载入天数...</span>
<span id="times">载入时分秒...</span>
<script src="/js/duration.js"></script>
</div>
'

然后,在站点根目录下创建 source/js/duration.js ,内容如下:

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
// 注意:文件以 utf8 编码,否则页面中文显示乱码。
var now = new Date();
function createtime() {
var grt = new Date("04/01/2025 00:00:00"); //在此处修改你的建站时间,格式:月/日/年 时:分:秒
now.setTime(now.getTime() + 250);
days = (now - grt) / 1000 / 60 / 60 / 24;
dnum = Math.floor(days);
hours = (now - grt) / 1000 / 60 / 60 - 24 * dnum;
hnum = Math.floor(hours);
if (String(hnum).length == 1) {
hnum = "0" + hnum;
}
minutes = (now - grt) / 1000 / 60 - 24 * 60 * dnum - 60 * hnum;
mnum = Math.floor(minutes);
if (String(mnum).length == 1) {
mnum = "0" + mnum;
}
seconds =
(now - grt) / 1000 - 24 * 60 * 60 * dnum - 60 * 60 * hnum - 60 * mnum;
snum = Math.round(seconds);
if (String(snum).length == 1) {
num = "0" + snum;
}
document.getElementById("timeDate").innerHTML =
"本站已安全运行 " + dnum + " 天 ";
document.getElementById("times").innerHTML =
hnum + " 小时 " + mnum + " 分 " + snum + " 秒";
}
setInterval("createtime()", 250);

页脚显示博客运行时间

强制全局 HTTPS

将所有请求强制升级为 HTTPS。避免域名升级到 HTTPS 后,站点引用资源出现 HTTP、HTTPS 混用的情况,造成资源无法显示。如是外部资源,需要本身支持 HTTPS。

1
2
3
# _config.fluid.yml

force_https: true

全局字体

详情见:配置指南:全局字体

该博文的操作比较繁琐:在 Hexo Fluid 主题中使用霞鹜文楷 - 竹林里有冰的博客

虽然官方推荐使用系统自带的字体,而不是额外引入字体(占内存导致浏览器渲染变慢),但改变字体能够让用户在浏览博客时具有更好的视觉体验。

霞鹜文楷 是一款开源中文字体,可免费商用。它字形漂亮,无论是做标题艺术字还是正文阅读都很舒适。


在主题配置文件引入【霞鹜文楷】css,并应用该字体:

1
2
3
4
5
6
7
8
# _config.fluid.yml

font:
# 全局字体族启用【霞鹜文楷】字体。
font_family: "LXGW WenKai Screen"
custom_css:
# 引入【霞鹜文楷】css。bootcdn 是稳定、快速、免费的前端开源项目 CDN 加速服务。
- https://cdn.bootcdn.net/ajax/libs/lxgw-wenkai-screen-webfont/1.7.0/style.min.css

2. 页面

页面:顶部大图

待参考:基于 JavaScript 的 Hexo Fluid 主题 banner 随机背景图实现 - 竹林里有冰的博客

banner:横幅

主题配置中,每个页面都有名为 banner_img 的属性,可以使用本地图片的路径,也可以为外站链接。

指向本地图片(本地指定图片):

1
2
3
4
5
# _config.fluid.yml

# 给出首页设置,其他页面同理。
index:
banner_img: /images/banner/粉女.jpg # 对应 source/images/banner/粉女.jpg

指向外站链接(外站指定图片或随机图片,取决于外链):

1
2
3
4
5
6
# _config.fluid.yml

# 给出首页设置,其他页面同理。
index:
# 图库挺好,就是资源下载很耗时,导致页面性能很差。todo:建立个人图库(没空)。
banner_img: https://api.seaya.link/web.php?type=file

【持续更新】75个二次元、三次元随机图API接口分享及预览 - 赵苦瓜のBlog


主题配置中的 post.banner_img 属性用于文章页统一设置所有博文的顶部大图。如果文章页的每篇博文需要单独设置顶部大图,可以在每篇文档的 Front-matter 部分指定 banner_img 属性值。

1
2
3
4
---
title: Fluid主题の博客美化
banner_img: /images/banner/粉女.jpg
---

主题配置文件优先级低于 Front-matter。 如果两处都未设置,则不显示。

博文页的顶部大图

首页:副标题打字机

如果设置副标题为固定的内容,修改 text 字段即可:

1
2
3
4
5
6
# _config.fluid.yml

index:
slogan:
enable: true # 默认为 true,即默认开启首页大图中的副标题文字。
text: "Cornpoppies, are you still burning, in the rain ..." # 副标题内容

固定的内容

如果副标题内容需要变化,也可以通过外链获取变化的内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
# _config.fluid.yml

index:
slogan:
enable: true # 默认为 true,即默认开启首页大图中的副标题文字。
text: "Cornpoppies, are you still burning, in the rain ..." # 副标题内容
# 通过api接口获取内容,如果请求失败则按 text 字段显示
api:
enable: true # 默认为 false,即仅按 text 字段显示。设置为 ture,使用外链。
url: "https://v1.hitokoto.cn/" # API 地址,必须返回的是一个 JSON 格式
method: "GET"
headers: {}
keys: ["hitokoto"] # 从请求结果中获取指定字段的值

变化的内容

首页:文章摘要

Fluid 主题默认会自动截取文章开头内容作为摘要显示在首页。

  • 因为文章开头的内容可能并不是摘要,可以在文档的 Front-matter 部分设置 excerpt 属性来取代默认行为。如果 excerpt 属性无值,记得删除该属性。
  • 如果博文的 title 能够概括其内容,而无需单独列出摘要,可以在主题配置文件中取消自动截取。
1
2
3
4
5
6
7
# _config.fluid.yml

index:
# 自动截取文章摘要
# Auto extract post
auto_excerpt:
enable: false # 设置为 false,关闭。

文章页:博文在首页的封面图

可以在主题配置文件中统一设置所有博文在首页的封面图:

1
2
3
4
5
# _config.fluid.yml

post:
# 首页封面图
default_index_img:

也可以在具体文档的 Front-matter 部分单独设置每篇博文在首页的封面图:

1
2
3
4
---
title: 使用Hexo搭建个人博客
index_img: /images/post/girl.jpg # 对应 source/images/post/girl.jpg
---

主题配置文件优先级低于 Front-matter。 如果两处都未设置,则不显示。

博文在首页的封面图

文章页:文章标题下方的元信息

文章标题下方的元信息显示【作者】和【浏览量计数】:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# _config.fluid.yml

post:
# 文章标题下方的元信息
meta:
# 作者,优先采用 front-matter 部分的 author 字段,其次是 hexo 配置中 author 值
author:
enable: ture # 设置为 ture,开启。

# 浏览量计数
views:
enable: true # 设置为 ture,开启。
# 统计数据来源
# Options: busuanzi | leancloud | umami
source: "busuanzi"

文章页:在文章开头显示文章更新时间

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# _config.fluid.yml

post:
# 在文章开头显示文章更新时间,该时间默认是 md 文件更新时间,
# 可在文档的 Front-matter 部分设置 `updated` 属性手动指定(和 date 一样格式)。
# 本人不设置该属性,采用 Hexo 默认读取的时间。
updated:
enable: true # 设置为 ture,开启。

# 格式参照 ISO-8601 日期格式化
date_format: "LL a"

# 是否使用相对时间表示,比如:"3 天前"
relative: false

# 提示标签类型。不同的类型显示不同的颜色。
# Options: default | primary | info | success | warning | danger | light
note_class: info

文章页:侧边栏展示当前分类下的文章

侧边栏【按指定顺序】展示当前分类下的文章:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# _config.fluid.yml

post:
# 侧边栏展示当前分类下的文章
category_bar:
enable: true # 设置为 ture,开启。

# 开启后,只有在文章 Front-matter 部分指定 `category_bar: true` 才会展示分类,也可以通过 `category_bar: ["分类A"]` 来指定分类
specific: true # 文档的 Front-matter 部分指定 `category_bar: true`

# 置于板块的左侧或右侧。
# Options: left | right
placement: left # 采用默认值 left 即可,目录栏默认在右侧。

# 文章的排序字段,前面带减号是倒序,不带减号是正序
# Options: date | title | or other field of front-matter
post_order_by: "category_order" # 文档的 Front-matter 部分指定 `category_order: 数字`

# 单个分类中折叠展示文章数的最大值,超过限制会显示 More,0 则不限制
post_limit: 0

文章页:Tag 便签

文章页 | 脚注

推荐使用 HTML 标签,而不是内置标签。

HTML 标签格式:<p class="note note-primary">元素内容</p> 。note-primary 代表一种颜色。

color of primary

color of secondary

color of success

color of danger

color of warning

color of info

color of light

3. 注入静态代码片段

可以在主题配置文件中设置要注入 js 或 css:

  1. custom_js: 部分注入到 </body>
  2. custom_css: 部分注入到 </head>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# _config.fluid.yml

# 指定自定义 .js 文件路径,支持列表;路径是相对 source 目录,如 /js/custom.js 对应存放目录 source/js/custom.js
custom_js:
- //cdn.jsdelivr.net/gh/bynotes/texiao/source/js/love.js # 鼠标点击特效:小爱心❤
- //cdn.jsdelivr.net/gh/bynotes/texiao/source/js/xiaoxuehua.js # 页面特效:小雪花飘落
- //cdn.jsdelivr.net/gh/EmoryHuang/[email protected]/Cherry.min.js # 页面特效:樱花飘落
- //cdn.jsdelivr.net/gh/EmoryHuang/[email protected]/DynamicLine.min.js # 页面特效:动态黑色线条

# 鼠标跟随特效:小星星。(操作 DOM 元素,耗性能,可改为 Canvas 实现。)
# - //cdn.jsdelivr.net/gh/bynotes/texiao/source/js/xiaoxingxing.js
# - //cdn.jsdelivr.net/gh/bynotes/texiao/source/js/caidai.js # 页面特效:动态彩带
# - //cdn.jsdelivr.net/gh/EmoryHuang/[email protected]/Ribbon.min.js # 页面特效:静态彩带

# 指定自定义 .css 文件路径,用法和 custom_js 相同
# The usage is the same as custom_js
custom_css:
# 引入【霞鹜文楷】css。bootcdn 是稳定、快速、免费的前端开源项目 CDN 加速服务。
- https://cdn.bootcdn.net/ajax/libs/lxgw-wenkai-screen-webfont/1.7.0/style.min.css
- https://jsd.cdn.zzko.cn/gh/EmoryHuang/[email protected]/gradient.css # 渐变打字机
- //cdn.jsdelivr.net/gh/bynotes/texiao/source/css/shubiao.css # 鼠标指针美化
- //cdn.jsdelivr.net/gh/bynotes/texiao/source/css/gundongtiao.css # 滚动条美化

Hexo 也提供了脚本与注入器:

  1. 在站点根目录下创建 scripts 文件夹,里面放入自定义脚本。Hexo 在生成网站时会自动加载它们。
  2. Hexo 提供注入器钩子,用于将静态代码片段注入到生成的 HTML 的 <head> 和/或 <body> 中。Hexo 会在after_render 过滤器(在渲染完成后对 JS 进行压缩)之前完成注入。

插件 | Hexo

注入器(Injector) | Hexo

双端背景

【舍去 banner,固定背景】:Fluid主题安装及配置 - Endlsee-Path的学习记录

设置响应式背景:

  • 根据窗口尺寸区分手机端和电脑端,实时切换背景。
  • 当 banner 占据页面小于一定比例,则显示背景;否则隐藏背景。

Tip:为了页面性能,可以选择固定背景。


在所有页面的 body 头部添加 div 元素。在文章页面的 body 尾部添加响应式背景程序,用于填充该 div 元素。

hexo/scripts/injector.js

1
2
3
4
5
6
const { root: siteRoot  =  "/" } =  hexo.config;

// <div> 注入到文章页的 <body> 之后,用于 responsive-background.js 自适应背景切换。
hexo.extend.injector.register("body_begin", '<div id="web_bg"></div>');
// <script> 注入到文章页的 </body> 之前
hexo.extend.injector.register("body_end",`<script src="${siteRoot}js/responsive-background.js"></script>`);

source/js/responsive-background.js

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
67
68
69
70
71
72
73
74
75
76
// 响应式背景:根据窗口尺寸区分手机端和电脑端,实时切换背景。当 banner 占据页面小于一定比例,则显示背景;否则隐藏背景。

// 定义背景图片链接(your bg address)
const mobileBgImageUrl = "url('/images/bg/和泉纱雾mob5.jpg')";
const desktopBgImageUrl = "url('/images/bg/bg.webp')";

// 获取元素
const webBg = document.querySelector('#web_bg');
const banner = document.querySelector('#banner');

// 控制是否在请求动画帧中执行
let isUpdating = false;

// 设置背景图片的函数
function setBackground() {
// window.innerWidth < 768,用来区分手机端和电脑端。
if (window.innerWidth < 768) {
// 手机端背景
webBg.style.backgroundImage = mobileBgImageUrl;
} else {
// 电脑端背景
webBg.style.backgroundImage = desktopBgImageUrl;
}
// 保持其他样式
webBg.style.position = 'fixed';
webBg.style.top = '0';
webBg.style.left = '0';
webBg.style.width = '100%';
webBg.style.height = '100%';
webBg.style.zIndex = '-1';
webBg.style.backgroundSize = 'cover';
webBg.style.backgroundRepeat = 'no-repeat';
}

// 根据 banner 在页面的占比,决定显示/隐藏 web_bg(背景)。
function updateVisibility() {
// 每次滚动时获取元素在视口中的位置和尺寸。
// bottom:元素底部距离视口顶部的距离。top:元素顶部距离视口顶部的距离。height:元素高度。
const rect = banner.getBoundingClientRect();

// 设置阈值。比如:视口高度(界面高度)的20%。
const threshold = window.innerHeight * 0.2;

if (rect.bottom > threshold) {
// 若 banner 底部距离视口顶部大于阈值,则隐藏背景。
webBg.style.display = 'none';
} else {
// 否则显示背景。
webBg.style.display = 'block';
}
isUpdating = false; // 允许下一帧更新
}

// 绑定 load 事件,页面加载时调用。
window.addEventListener('load', () => {
setBackground(); // 页面加载时设置背景
updateVisibility(); // 初次检测
});

// 绑定 resize 事件,窗口变化时调用。
window.addEventListener('resize', () => {
setBackground(); // 改变窗口时设置背景
// 立即检测 banner 位置,调整背景显示状态。
if (!isUpdating) {
isUpdating = true;
window.requestAnimationFrame(updateVisibility);
}
});

// 绑定滚动事件,鼠标滚动时调用。
window.addEventListener('scroll', () => {
if (!isUpdating) {
isUpdating = true;
window.requestAnimationFrame(updateVisibility);
}
});

说明:

  • 使用 requestAnimationFrame 确保在每一帧只调用一次 updateVisibility ,避免滚动频繁触发造成的性能问题。
  • isUpdating 变量用来避免重复请求动画帧。
  • loadresize 事件中也调用 setBackground(),确保背景在窗口变化时正确设置。

滚动事件会在用户滚动时频繁触发,可能每秒触发几十次甚至上百次。每次触发,调用 getBoundingClientRect() 和修改样式会触发浏览器的布局(reflow)和绘制(repaint),非常耗费性能,导致页面卡顿。

requestAnimationFrame 是浏览器提供的 API,用于在浏览器下一次重绘之前执行回调函数。它会在浏览器准备好绘制下一帧时调用,通常每秒大约 60 次(每 16 毫秒左右),但如果多次请求,浏览器会合并成一次调用,避免多次重复执行。

在滚动或窗口变化事件中,设置一个标志(如isUpdating)。确保在一帧中只发起一次 requestAnimationFrame 请求。控制请求频率,防止请求堆积。实现 updateVisibility 最多每一帧执行一次。


Fluid主题の博客美化
https://cornst.com/posts/Fluid主题の博客美化.html
作者
shaton沙桐
发布于
2025年4月26日
更新于
2025年5月20日
许可协议