前言: 编程的乐趣不仅在于构建庞大的系统,也在于打磨属于自己的方寸之地。 这两天,我对个人的 Hexo 博客进行了深度的“外科手术式”改造。从导航栏的像素级对齐,到项目展示页的工程化解耦,每一步都贯彻了“高内聚、低耦合”的软件工程美学。本文将详细复盘所有核心技术点与踩坑经验。
一、 顶层交互重构:悬浮胶囊导航栏 (Glassmorphism)
为了摆脱传统博客沉闷的顶部栏,我决定复刻移动端 APP 的交互逻辑,实现**“左侧菜单 - 中间标题 - 右侧搜索”**的对称布局,并赋予其磨砂玻璃(Glassmorphism)质感。
1.1 CSS Flex 布局的妙用
Butterfly 主题默认在 PC 端隐藏了“三条杠”菜单(Hamburger Menu)。为了强制显示并重排顺序,我利用了 Flexbox 的 order 属性。
核心难点:
- 如何打破 DOM 结构的默认顺序?
- 如何解决 PC 端 CSS 权重导致的
display: none 问题?
解决方案 (custom.css):
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
| /* 容器:开启 Flex 布局,准备排序 */ #nav { display: flex !important; justify-content: center !important; /* 让“达芬奇”三个字在正中间 */ align-items: center !important; /* 垂直居中 */ /* 磨砂玻璃质感核心 */ position: fixed !important; top: 20px !important; background: rgba(255, 255, 255, 0.2) !important; backdrop-filter: blur(12px) saturate(160%) !important; /* 毛玻璃模糊 */ border-radius: 50px !important; /* 胶囊形状 */ border: 1px solid rgba(255, 255, 255, 0.3) !important; box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.15) !important; }
/* 强制召唤三条杠,并移至最左侧 */ #nav #toggle-menu { display: flex !important; /* 覆盖主题的隐藏规则 */ order: -1 !important; /* 🔥 核心:-1 代表插队到第一位 */ margin-right: 15px !important; padding: 0 !important; }
/* 隐藏原来冗余的文字菜单 */ #nav #menus { display: none !important; }
|
1.2 搜索按钮的对称定位
为了配合左侧的菜单,右侧必须放置搜索按钮以保持视觉平衡。这里涉及到 CSS calc() 函数的动态计算。
JS 动态定位 (fancy-search.js):
1 2 3 4 5 6 7 8 9
| // 强制将搜索按钮定位到右侧对称位置 const searchBtn = document.getElementById('search-trigger-btn'); if (searchBtn) { searchBtn.style.position = 'fixed'; searchBtn.style.top = '20px'; searchBtn.style.left = 'auto'; /* 距离中心向右偏移 160px,与左侧菜单形成完美对称 */ searchBtn.style.right = 'calc(50% - 160px)'; }
|
二、 核心功能开发:项目工坊 (Project Gallery)
这是本次改造的重头戏。我需要一个专门的页面来展示“尚庭公寓”、“分布式商城”等实战项目。
2.1 演进路线:从 Hardcode 到 Tag Plugin
- V1.0 (HTML 硬编码):直接在 Markdown 里写大量的
<div class="...">。
- 缺点:代码臃肿,难以维护,容易因缩进问题导致渲染错误。
- V2.0 (工程化解耦):使用 Hexo 的 Tag Plugin 机制,编写自定义脚本。
- 优点:Markdown 里只需一行代码,自动生成复杂的 HTML 结构。
2.2 逻辑层:自定义 Tag 插件
在 scripts/project-card.js 中,我注册了一个名为 project 的标签。它支持接收动态参数(链接、封面、标题、描述、技术栈标签)。
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
| /** * project-card.js * 使用方法: {% project link img title desc tag1 color1 ... %} */ hexo.extend.tag.register('project', function(args) { const link = args[0]; const img = args[1]; const title = args[2]; const desc = args[3];
// 动态解析不定长参数:生成技术栈标签 let tagsHtml = ''; for (let i = 4; i < args.length; i += 2) { const tagName = args[i]; const color = args[i + 1] || 'blue'; tagsHtml += `<span class="tag-pill ${color}">${tagName}</span>`; }
// 返回纯净的 HTML 结构 return ` <a class="project-card" href="${link}"> <div class="card-cover" style="background-image: url('${img}')"> <div class="card-overlay"></div> </div> <div class="card-info"> <div class="card-title">${title}</div> <div class="card-desc">${desc}</div> <div class="card-tags">${tagsHtml}</div> </div> </a>`; });
|
2.3 表现层:CSS 卡片样式
在 custom.css 中,实现了卡片的悬浮特效和标签配色。
1 2 3 4 5 6 7 8 9 10 11
| /* 悬停特效:上浮 + 蓝光阴影 */ .project-card:hover { transform: translateY(-10px); box-shadow: 0 20px 40px rgba(66, 90, 239, 0.15); border-color: #425AEF; }
/* 标签配色系统 */ .tag-pill.blue { background: rgba(33, 150, 243, 0.1); color: #2196f3; } .tag-pill.purple { background: rgba(156, 39, 176, 0.1); color: #7b1fa2; } /* ...更多颜色... */
|
2.4 数据层:一行代码调用
最终,在 source/projects/index.md 中,我们只需要这样写:
1
| {% project /tags/BlogDev/ /img/blog.jpg "个人博客开发日志" "记录本站从零搭建的过程。" Hexo blue Butterfly purple %}
|
这一步真正实现了内容与样式的彻底分离。
三、 细节体验优化
3.1 归档页与“热门”逻辑重构
原本的“热门”按钮通常指向一些复杂的统计页。为了简化逻辑并提供更好的保底体验,我将其直接重定向至归档页 (/archives/)。
同时,对归档页进行了**“去侧边栏”**处理,让时间轴内容占据全屏,配合动态波浪背景,视觉冲击力极强。
1 2 3 4 5
| // source/js/fancy-search.js const LINKS = { hot: '/archives/', // 🔥 巧妙的逻辑替换:热门 -> 时间轴归档 // ... };
|
3.2 字体与排版
全站标题引入了 Google Fonts 的 Playfair Display(意大利斜体),并强制应用了文字阴影,营造出杂志封面的高级感。
四、 踩坑与教训 (Debug Log)
在开发过程中,也遇到了一些典型的错误,记录如下以自省:
4.1 YAML 语法缩进灾难
在配置 _config.butterfly.yml 菜单时,遇到了 YAMLException。
- 错误原因:使用了中文冒号
:,以及在列表项缩进上不统一。
- 解决:YAML 必须严格使用双空格缩进,且所有冒号必须是英文冒号,冒号后必须紧跟空格。
4.2 HTML 标签与 Markdown 冲突
在 Markdown 文件中直接写 HTML 时,如果前面有缩进(Tab 或空格),Hexo 会将其解析为代码块而非渲染 DOM。
- 解决:HTML 标签或 Tag 插件代码必须顶格书写。
4.3 标签参数解析错误
在使用自定义 Tag 插件时,曾出现标签颜色显示为 blue 字样的情况。
- 原因:参数顺序写反了(写成了
blue Hexo)。
- 解决:严格遵循
[文字] [颜色] 的参数对顺序。
五、 总结与展望
通过这两天的重构,本站已经从一个默认的 Hexo 模板,变身为一个具有高度个人特色的技术展示平台。我们实现了:
- 工程化:通过 JS 脚本封装组件。
- 美学化:磨砂玻璃与流体动画的运用。
- 人性化:符合直觉的导航与交互。