本文最后更新于 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
属性
网站图标:修改主题配置文件(_config.fluid.yml
)的 favicon
属性
1 2 3 4 5 6 7 8 9 favicon: /images/favicon/shaton.ico apple_touch_icon: /images/favicon/shaton.ico
页头导航栏:左侧的标题 1 2 3 4 navbar: blog_title: "shaton沙桐的乐色桶"
二级目录: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 footer: statistics: enable: true source: "busuanzi" pv_format: "总访问量 {} 次" uv_format: "总访客数 {} 人"
页脚:添加博客运行时间 首先,在主题配置的 footer.content
部分添加 <div>
标签,内容如下:
1 2 3 4 5 6 7 8 9 10 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 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。
全局字体
详情见:配置指南:全局字体
该博文的操作比较繁琐:在 Hexo Fluid 主题中使用霞鹜文楷 - 竹林里有冰的博客
虽然官方推荐使用系统自带的字体,而不是额外引入字体(占内存导致浏览器渲染变慢),但改变字体能够让用户在浏览博客时具有更好的视觉体验。
霞鹜文楷 是一款开源中文字体,可免费商用。它字形漂亮,无论是做标题艺术字还是正文阅读都很舒适。
在主题配置文件引入【霞鹜文楷】css,并应用该字体:
1 2 3 4 5 6 7 8 font: font_family: "LXGW WenKai Screen" custom_css: - 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 index: banner_img: /images/banner/粉女.jpg
指向外站链接(外站指定图片或随机图片,取决于外链):
1 2 3 4 5 6 index: 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 index: slogan: enable: true text: "Cornpoppies, are you still burning, in the rain ..."
如果副标题内容需要变化,也可以通过外链获取变化的内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 index: slogan: enable: true text: "Cornpoppies, are you still burning, in the rain ..." api: enable: true url: "https://v1.hitokoto.cn/" method: "GET" headers: {} keys: ["hitokoto" ]
首页:文章摘要 Fluid 主题默认会自动截取文章开头内容作为摘要显示在首页。
因为文章开头的内容可能并不是摘要,可以在文档的 Front-matter 部分设置 excerpt 属性来取代默认行为。如果 excerpt 属性无值,记得删除该属性。
如果博文的 title 能够概括其内容,而无需单独列出摘要,可以在主题配置文件中取消自动截取。
1 2 3 4 5 6 7 index: auto_excerpt: enable: false
文章页:博文在首页的封面图 可以在主题配置文件中统一设置所有博文在首页的封面图:
1 2 3 4 5 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 post: meta: author: enable: ture views: enable: true source: "busuanzi"
文章页:在文章开头显示文章更新时间 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 post: updated: enable: true date_format: "LL a" relative: false note_class: info
文章页:侧边栏展示当前分类下的文章 侧边栏【按指定顺序】展示当前分类下的文章:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 post: category_bar: enable: true specific: true placement: left post_order_by: "category_order" 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:
custom_js:
部分注入到 </body>
前
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 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 custom_css: - 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 也提供了脚本与注入器:
在站点根目录下创建 scripts 文件夹,里面放入自定义脚本。Hexo 在生成网站时会自动加载它们。
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 ; hexo.extend .injector .register ("body_begin" , '<div id="web_bg"></div>' ); 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 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 ( ) { 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' ; }function updateVisibility ( ) { const rect = banner.getBoundingClientRect (); const threshold = window .innerHeight * 0.2 ; if (rect.bottom > threshold) { webBg.style .display = 'none' ; } else { webBg.style .display = 'block' ; } isUpdating = false ; }window .addEventListener ('load' , () => { setBackground (); updateVisibility (); });window .addEventListener ('resize' , () => { setBackground (); if (!isUpdating) { isUpdating = true ; window .requestAnimationFrame (updateVisibility); } });window .addEventListener ('scroll' , () => { if (!isUpdating) { isUpdating = true ; window .requestAnimationFrame (updateVisibility); } });
说明:
使用 requestAnimationFrame
确保在每一帧只调用一次 updateVisibility
,避免滚动频繁触发造成的性能问题。
isUpdating
变量用来避免重复请求动画帧。
在 load
和 resize
事件中也调用 setBackground()
,确保背景在窗口变化时正确设置。
滚动事件会在用户滚动时频繁触发,可能每秒触发几十次甚至上百次。每次触发,调用 getBoundingClientRect()
和修改样式会触发浏览器的布局(reflow)和绘制(repaint),非常耗费性能,导致页面卡顿。
requestAnimationFrame
是浏览器提供的 API,用于在浏览器下一次重绘之前执行回调函数。它会在浏览器准备好绘制下一帧时调用,通常每秒大约 60 次(每 16 毫秒左右),但如果多次请求,浏览器会合并成一次调用,避免多次重复执行。
在滚动或窗口变化事件中,设置一个标志(如isUpdating
)。确保在一帧中只发起一次 requestAnimationFrame
请求。控制请求频率,防止请求堆积。实现 updateVisibility
最多每一帧执行一次。