/tags/ 往往是博客里最容易被忽视、却又最容易失控的一个页面。
一开始标签不多时,按 tag 逐组平铺文章没有什么问题;但只要文章一增多、每篇文章开始拥有多个标签,页面就会迅速变得拥挤:同一篇文章在不同 tag 下重复出现,视觉上像一面被不断复制粘贴的墙。
这次,我决定把这个页面彻底重构一下。
旧版 Tags 页的问题
原先的实现逻辑很直接:
- 先遍历
site.tags,在页面顶部输出一组标签链接; - 再继续遍历
site.tags,为每个标签渲染一段文章列表; - 右侧额外放一个自由漂浮的词云作为视觉装饰。
这种写法在代码上不复杂,但在体验上会带来三个明显问题:
1. 一篇文章会重复出现很多次
如果某篇文章同时拥有 Jekyll、Liquid、Workflow 三个标签,那么它会在三个分组里各出现一次。标签越多,重复越明显。
2. 页面焦点被切碎了
顶部标签、右侧词云、正文长列表同时争夺注意力。用户点开页面后,并不知道应该先看哪里。
3. Tags 页不像“索引”,更像“堆叠”
它确实展示了很多信息,但缺少真正的检索能力。用户若想快速找到某篇文章,往往还得反复滚动页面。
这次的重构目标
我希望新的 Tags 页承担的是“统一内容索引入口”的角色,而不是标签展示墙。因此,这次重构主要围绕四个目标展开:
- 每篇文章只出现一次;
- 标签可以点击筛选;
- 支持全文范围内的即时搜索;
- 页面结构更安静,视觉层次更清楚。
新版页面的结构调整
1. 顶部从“词云入口”改为“概览面板”
新版页面先展示一个总览区域,直接告诉读者:
- 当前共有多少篇文章;
- 一共维护了多少个标签;
- 站内有多少个专栏或分组。
这样一来,用户进入页面后的第一感受不再是“好多东西”,而是“这个页面是有组织的”。
2. 标签区改成可筛选的 chips
标签本身仍然保留,但不再承担“跳到某个冗长锚点”的职责,而是变成一组可以即时筛选内容的按钮。
每个 chip 会显示:
- 标签名称;
- 该标签关联的文章数量。
点一下,就只看这一类文章;再配合“清除筛选”,整个交互会顺很多。
3. 主内容区改成去重后的文章卡片
这是这次重构最核心的变化。
不再按 tag 循环文章,而是直接遍历 site.posts,把每篇文章渲染成一张卡片。卡片里统一展示:
- 标题
- subtitle(如果有)
- 日期
- 所属专栏
- tags
- 摘要
这样无论一篇文章拥有几个标签,它在页面里都只会出现一次。
4. 搜索能力加入标题、摘要、标签和专栏名
为了让 Tags 页真的具备“索引”意义,我还给页面加了前端即时搜索。
现在搜索框会同时匹配:
- 标题
- 副标题
- 摘要
- 标签
- 分组名称
对于文章数量还不算特别夸张的静态博客来说,这种纯前端筛选已经足够轻量,也足够实用。
实现思路:Liquid 负责出数据,JavaScript 负责筛选
这次改造没有引入额外插件,仍然保持 Jekyll 原生能力。
思路很简单:
在 Liquid 层完成页面骨架
Liquid 负责:
- 输出标签 chips;
- 遍历
site.posts生成文章卡片; - 为每张卡片写入
data-search、data-tags等属性。
这样浏览器拿到的 HTML 本身就是完整可读的,哪怕 JavaScript 失效,页面也仍然是一个正常的文章列表。
在 JavaScript 层完成交互筛选
JavaScript 只负责三件事:
- 记录当前激活的标签;
- 监听搜索框输入;
- 计算哪些卡片应当显示、哪些应当隐藏。
这是一种很适合静态博客的分工方式:
- 模板层负责内容组织;
- 交互层负责轻量增强;
- 页面不会因为追求炫技而变得难维护。
为什么我删掉了右侧漂浮词云
漂浮词云的确有一定“看起来很酷”的效果,但它更像视觉装饰,而不是高价值交互。
当一个页面已经承担“检索入口”的任务时,信息的秩序感会比装饰感更重要。
所以这次我做了一个取舍:
- 保留标签本身;
- 去掉会分散注意力的漂浮词云;
- 把视觉重点让给搜索、筛选和文章卡片。
换句话说,这次不是把页面做得更“花”,而是把它做得更“有用”。
一个小结
这次 Tags 页重构,本质上不是单纯换个样式,而是重新定义它的职责:
它不该只是“标签的展示页”,而应该是“博客内容的二级入口”。
当页面角色想清楚以后,很多设计决策其实都自然了:
- 去重,而不是重复堆文章;
- 搜索,而不是只会跳锚点;
- 标签筛选,而不是视觉漂浮物;
- 卡片式摘要,而不是无限向下的重复列表。
如果后面文章越来越多,这一套结构也更容易继续扩展,比如再加上“按专栏筛选”“按年份筛选”甚至“默认推荐排序”等能力。
到这里,这个博客的内容组织方式终于又往前走了一步。