统一博客 UI/UX:从动效、间距到构建产物清理
这次优化主要围绕博客的 UI/UX 一致性 展开。前一轮已经把站点调整到更严格的 no-JS 输出方式,这一轮则进一步处理视觉层面的细节:让交互反馈更稳定、间距和圆角更统一,减少界面里的装饰性干扰。
同时,构建脚本也做了一个小改进:自动清理旧的 hash CSS 文件,避免 _site/assets/ 随着多次增量构建不断积累历史资源。
增加统一的设计变量
之前 CSS 中散落着大量直接写死的 4px、8px、15px、20px、40px 等值。它们单独看都合理,但长期维护时容易让组件之间的空间关系变得不一致。
这次在 :root 中增加了一组统一变量:
:root {
--space-xs: 4px;
--space-sm: 8px;
--space-md: 16px;
--space-lg: 24px;
--space-xl: 40px;
--radius-sm: 4px;
--radius-md: 8px;
--radius-pill: 999px;
--content-width: 800px;
--reading-width: 68ch;
}
随后将页面容器、主内容布局、移动端目录、文章列表、标签云、归档列表、页脚、按钮和上下篇导航等主要组件逐步接入这些变量。
这样做的好处是:以后如果想调整整体密度或圆角风格,只需要改变量本身,而不必在整份 CSS 里逐个搜索数字。
统一当前页导航状态
模板里原本已经输出了 aria-current="page",但 CSS 主要识别的是 .active-nav-link。这会造成语义状态和视觉状态没有完全对齐。
现在导航高亮改为同时支持:
header nav a:hover,
header nav a.active-nav-link,
header nav a[aria-current="page"] {
color: var(--color-main-text);
font-weight: 600;
}
这样当前页面既能被辅助技术正确识别,也能在视觉上保持一致。
收敛 hover 动效
之前不同组件的 hover 反馈不完全一致:
- 文章列表项会横向位移;
- 标签云会轻微上移;
- 按钮会向上浮动;
- 页脚链接会向上浮动;
- 上下篇导航卡片会整体上浮;
- 图片 hover 时会缩放。
这些交互单独看都不算问题,但放在同一个极简博客里会有一点“跳动感”。这次统一把主要交互收敛为:
- 颜色变化;
- 背景变化;
- 边框变化;
- 少量阴影变化。
文章卡片、标签、按钮、页脚链接、归档项和上下篇导航都不再使用位移动效。这样页面在鼠标移动时更稳定,也更符合内容型站点的阅读气质。
清理元信息里的 emoji
首页文章列表之前使用了 📅 表示日期、🏷️ 表示标签,移动端目录标题也用了 📑。这些符号比较醒目,但和站点当前偏文档化、极简化的方向不完全一致。
这次只清理 UI 元信息里的 emoji:
- 日期只显示日期文本;
- 标签只显示标签名;
- 移动端目录标题改为纯文字“目录”。
文章标题和正文里的 emoji 没有强制移除,因为它们属于作者内容的一部分,而不是界面控件。
自动清理旧 CSS 构建产物
CSS 文件使用内容 hash 生成文件名,例如:
style.b069f486.css
这种方式有利于缓存控制,但在增量构建时,旧 hash 文件会留在 _site/assets/ 中。多次构建后,本地目录里可能同时存在多个历史 CSS 文件。
这次在 autobuild.py 中增加了清理逻辑:每次生成新的 style.<hash>.css 后,自动删除同目录下其他旧的 style.*.css。
构建日志会显示类似信息:
Removed stale CSS asset: style.b069f486.css
这样可以保持部署产物更干净,也减少无用静态资源。
构建验证
修改完成后重新运行:
python3 autobuild.py
构建通过,并确认:
- 首页列表中的日期和标签不再显示装饰性 emoji;
- 当前导航项仍然保留
aria-current="page"; - CSS 中主要组件已开始使用统一 spacing / radius 变量;
- 旧 CSS hash 文件会在构建过程中自动清理;
- 构建产物仍然保持无 JavaScript 运行时依赖。
第二轮细化:去掉模板内联样式
第一轮整理后,模板里还残留了少量内联样式,例如标签页文章数量和分割线:
<p style="...">共 N 篇文章</p>
<hr style="...">
这类写法会让样式分散在模板里,也会让 CSP 难以进一步收紧。现在它们被替换为明确的 CSS class:
<p class="tag-count">共 N 篇文章</p>
<hr class="section-divider">
样式集中回到 assets/style.css 中维护。这样模板更干净,也更符合“结构归 HTML,表现归 CSS”的原则。
第二轮细化:首页标签可点击
之前文章页的标签是链接,而首页列表中的标签只是普通 span。两者看起来相似,但交互行为不同,用户可能会以为首页标签也能点击。
这次把首页和标签页列表的标签也改成链接:
<a href="/tags/ui-ux/" class="tag-badge">ui-ux</a>
同时文章列表项不再整体包裹在 <a> 中,而是改为:
<article class="post-list-item">
<h2 class="post-title">
<a href="/posts/04/" class="post-title-link">文章标题</a>
</h2>
...
</article>
这样可以避免嵌套链接,也让标题链接和标签链接各自承担清晰的交互职责。
第二轮细化:表格对齐改用 class
Markdown 表格对齐通常会生成类似这样的内联样式:
<th style="text-align: center;">居中</th>
为了继续收紧 CSP,这次在解析阶段把这些内联样式转换为 class:
<th class="align-center">居中</th>
<td class="align-right">右对齐</td>
<td class="align-left">左对齐</td>
对应样式统一写在 CSS 中:
.post-content .align-left { text-align: left; }
.post-content .align-center { text-align: center; }
.post-content .align-right { text-align: right; }
这样最终 HTML 不再需要 style 属性。
第二轮细化:CSP 去掉 unsafe-inline
因为模板内联样式和表格内联对齐都已经清理,部署配置里的 CSP 也可以进一步收紧。
之前:
style-src 'self' 'unsafe-inline'
现在:
style-src 'self'
这意味着页面只允许加载同源 CSS 文件,不再允许任意内联样式。结合前面已经设置的 script-src 'none',整个站点的运行时约束更清晰。
第二轮细化:归档、代码块、图片和 Footer
这次还顺手处理了几个视觉细节:
- 归档列表加入和文章列表一致的左侧 hover 高亮条;
- 代码块移除了 macOS 红黄绿点,保留语言标签,减少视觉噪音;
- 代码块顶部留白缩小,正文节奏更紧凑;
- 暗色模式下正文图片不再默认降低透明度,避免影响截图、图表和插图的可读性;
- Footer 链接从背景块改为更轻的文本链接反馈;
- 文章正文列表移除每个列表项的虚线和 hover 背景,长列表阅读更安静;
- 锚点偏移改为
--header-offset和--header-offset-mobile变量,便于后续统一调整。
这些改动都不改变内容结构,但会让页面更像一个稳定的文档站,而不是交互组件堆叠出来的界面。
第三轮收尾:更安静的文档站体验
第二轮之后,又继续做了一次偏细节的收尾,目标是让页面更接近“文档站”的气质:信息层级清楚、视觉噪音更少,并且在空数据和移动端场景下也有完整表现。
首先修复了示例文章里的坏图。markdown/02.md 原本会实际渲染:

但仓库里并没有对应的 /logo.png。现在这段只作为 Markdown 语法示例保留在代码块中,不再生成一个失效图片请求。重新构建后,HTML 和 RSS 输出里也不再包含这个坏图。
移动端导航也做了收紧。小屏下 header 不再强制变成占用较高的纵向块,而是让站点标题和导航在空间允许时保持同一行,导航项可以横向换行。到更窄的 600px 以下时,再回到更自然的左对齐换行布局。这样 375px 宽度下顶部区域更轻,正文能更早进入视野。
代码块继续弱化了装饰感:移除了默认阴影和 hover 阴影,只保留边框、浅背景和右上角语言标签。hover 时仅轻微改变边框颜色,长文阅读时不会因为代码块卡片感太重而打断节奏。
标签详情页的“所有标签”入口也从按钮感改成了轻量文本链接。它仍然方便返回标签总览,但不再和文章标题、文章列表争夺视觉权重。
Footer 则进一步简化,只保留三类信息:
- 版权;
- RSS 订阅;
- 返回顶部。
构建时间或自定义 footer 文案不再输出到页面底部。对于这个博客当前的方向来说,Footer 更像文档页脚,而不是功能区。
最后补上了统一空状态。首页或标签页没有文章时,会显示“还没有发布文章”或“这个标签下还没有文章”;归档为空时显示“还没有可归档的文章”;标签列表为空时显示“还没有任何标签”。这些提示统一使用 empty-state 样式,保证模板在极端数据情况下也不会显得残缺。
小结
这次优化没有改变博客的信息架构,也没有引入新的功能模块。它更像一次视觉语言的整理:把动效收回来,把间距和圆角统一起来,把界面元信息做得更安静。
对于一个以 no-JS 和静态文档为目标的博客来说,稳定、克制、一致的 UI,比复杂交互更重要。第二轮细化后,站点不仅看起来更统一,HTML 和 CSP 也更干净。