页脚整理:把五块平铺信息改成三段式层次

博客改到现在,页脚一直是我不太愿意看的部分。

打开页面往下一滚,页脚就是一串平铺的文本:备案号、版权年份、访问统计、驱动声明,然后是定位语、一言、几个链接。信息本身都不缺,但排在一起就是乱。

不是内容的问题,是层次的问题。这篇把排查过程和改法都记下来。


一、先看看到底乱在哪

页脚一共有 5 个平铺的 div(.beian / .copyright / .busuanzi-count / .powered-by / .footer-brand),它们都继承 .footer-inner 的 text-align: center,理论上都是居中的。

但真正扎眼的是最后那块品牌栏,它的结构是这样的:

1
2
3
4
5
6
7
8
<div class="footer-brand">          <!-- display:flex; align-items:center -->
<span class="footer-spirit">🌸</span>
<div class="footer-brand-text"> <!-- 内部三行,全部 text-align:left -->
<p class="footer-brand-slogan">折腾不止,热爱不停</p>
<p class="footer-hitokoto">…</p>
<nav class="footer-brand-links">…</nav>
</div>
</div>

align-items: center 让那个 42px 的旋转图标垂直居中于整个三行文本块的高度,而不是与第一行 slogan 对齐。结果就是图标悬在中间偏下的位置,跟它本该修饰的那行字完全脱节。

再加上三行文字自身是左对齐的,整块内容重心明显偏左,跟上方那几行严格居中的版权文字对不上——就像两拨人各说各话。

还有个次要问题:分隔用的是 border-bottom: 1px dashed,引言用的是 border-left: 2px solid。一虚一实两道线,把本来就不宽的页脚切成了很多小碎片。

页脚信息层次改造前后对比


二、改法:三段式,而不是「一堆 div」

核心思路是给每一层信息一个专属的视觉语言,而不是靠线条和缩进去区分:

层次内容视觉语言
1定位语徽标(30px 圆形)+ 加粗大字,图标与文字同行
2一言圆角卡片,浅底 + 细边,文字居中,引号做背景装饰
3快捷入口等宽胶囊按钮,横向居中排布
4版权 / 备案12.5px 小字,收到最底部

对应到 HTML 上,最关键的一步是把 slogan 从文本块里提出来,和图标并排放:

1
2
3
4
<p class="footer-brand-slogan">
<span class="footer-spirit"><i class="fas fa-spa"></i></span>
<span>折腾不止,热爱不停</span>
</p>

这样 align-items: center 就作用在「图标 vs 一行文字」之间,基线自然对齐,不再有错位问题。

.footer-brand 本身改成 flex-direction: column; align-items: center,所有内容共用同一条居中轴:

1
2
3
4
5
6
7
8
9
10
.footer-brand {
order: -1; // 整块提到页脚最上方
display: flex;
flex-direction: column;
align-items: center;
gap: 12px;
margin-bottom: 16px;
padding-bottom: 16px;
border-bottom: 1px solid var(--border);
}

1. 让品牌栏排到最上面

order: -1 是个小技巧。.footer-brand 在 DOM 里是 NexT 注入在 .footer-inner 末尾的(主题自己的版权块在前),但视觉上「站点定位语」应该是页脚的第一句,版权信息才是最后的收尾。

.footer-inner 本身也是 flex 容器(display: flex; flex-direction: column),所以 order 直接生效,不需要动任何 JS。

2. 一言改成卡片

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
.footer-hitokoto {
position: relative;
min-width: 380px; // 防止短句时卡片缩成一条
max-width: 560px;
padding: 11px 22px;
border-radius: var(--radius-sm);
background: var(--surface-sunken);
border: 1px solid var(--border);
text-align: center;

i { // 引号脱离文字流,做成背景装饰
position: absolute;
top: 6px; left: 10px;
color: var(--accent-line);
opacity: 0.7;
}
}

引号原来是 <i> 内联在文字前面的。改成绝对定位之后,它不再参与文字流,句子才能真正居中——否则前面挂着一个图标,整段文字看起来永远是偏的。

min-width 是实测出来的:短句时卡片会被内容撑得只有 200px 出头,在宽屏下显得很寒碜。

出处(.fh-from)是 JS 动态 append 进去的 span,给它加 display: block 让它单独成行:

1
2
3
4
5
6
.fh-from {
display: block;
margin-top: 2px;
color: var(--text-faint);
font-size: 12px;
}

3. 快捷入口改成胶囊

1
2
3
4
5
6
.footer-brand-links a {
padding: 5px 14px;
border-radius: var(--radius-pill);
border: 1px solid var(--border);
background: var(--surface-sunken);
}

原来只是几个裸链接加图标,靠 gap: 14px 撑开。改成胶囊后每个入口有明确的点击边界,视觉上更「实」。


三、顺手清掉一个失效的第三方脚本

整理页脚时发现 .busuanzi-count 这一块的域名 busuanzi.ibruce.info 已经解析不了,每次加载都在控制台刷 ERR_NAME_NOT_RESOLVED,页面上留下一行空白,还白占一次 DNS 解析。

这种「配了但早就死了」的东西最容易被忽略——因为它不影响功能,只影响噪音。既然首页已经有统计胶囊了,直接在 _config.next.yml 里关掉:

1
2
busuanzi_count:
enable: false

比在 CSS 里 display: none 强:后者只是把症状藏起来,脚本照样加载、照样报错。


四、几条可复用的经验

1. Flex 容器里 align-items: center 是双刃剑。
它让「图标 + 文字」这组配对自然居中,但前提是两者高度应该接近。如果一边是 42px 的图标、一边是三行 96px 的文本块,居中出来的结果一定是错位的。遇到这种情况,先检查是不是该改成 flex-start 或者干脆把元素拆成同层兄弟。

2. 装饰性图标应该脱离文字流。
想让它「浮在」内容上就用 position: absolute,想让它「跟在」文字前就用 inline。两者混用是最容易出问题的——比如引号挂在句首,句子就永远居中不了。

3. 移动端要单独看,不要只靠 @media 猜。
这次改完我截了 390px 宽度下的图:胶囊按钮自动换成两排,引文卡片的 min-width 用 min-width: 0 覆盖掉(否则 380px 会撑破窄屏),视觉上依然整齐。@media 里该写的还得写。

4. 数字和文字混排时,注意字重和字号的落差。
数字用等宽字体 + 800 字重 + 19px,旁边的说明文字 12.5px,落差够大才读得出「这是两个东西」。


五、验证

改完按惯例做三件事:

1
2
npx hexo clean && npx hexo generate
stat -c%s public/index.html # 确认不是 0 字节

然后用 playwright 分别截了浅色、深色、移动端三种形态,确认:

  • 浅色(樱粉):三段式层次清晰,胶囊按钮边界明确
  • 深色(藤紫):卡片与背景对比正常,--surface-sunken 在深色下自动变深
  • 移动端(390px):胶囊换行成两排,引文卡片自适应宽度

最后一步是把 body.darkmode 手动加上再截图——主题的深色切换是 JS 控制的,单纯改 prefers-color-scheme 媒体查询在截图里不一定生效。


一句话总结:页脚乱,往往不是内容太多,而是所有信息用了同一种视觉语言。给每一层一个专属的表达方式(徽标 / 卡片 / 胶囊 / 小字),杂乱感自然就消失了。