2026.06.11 (四)

✨ GPT-5.5 的摘要  

为了减少 Kramdown 默认脚注从正文跳到页面底部参考资料区的不便,在保留既有脚注结构的同时,把正文脚注链接改成 [1] 形式的弹出层 UI 的记录。

开始认真使用脚注之后,不便立刻显出来了。

博客文章里处理外部新闻或资料时,我现在会在正文旁边加 Kramdown footnote。尤其是选票不足这一前所未有的事件、愤怒与极端主义者的危害这样的文章,事实关系很多,所以脚注也相当多。

但实际读起来,流程不太好。

在正文里点击脚注编号时,并不会弹出窗口,而是直接移动到页面最底部的参考资料区域。作为默认行为,这是对的。Kramdown 本来就是这样生成脚注的。但在长文里,很容易丢掉刚才正在读的位置。

脚注编号的样子也有点尴尬。

如果只是像1 2 3 4这样贴着很小的数字,就很难点。尤其在手机上更明显。在正文中间准确点到一个小数字,比想象中更费神。

所以这次稍微改了一下脚注系统。

在正文里显示成[1][2][3],点击时不再跳到最底部,而是打开一个小弹出层。

没有动 Kramdown 的结构

一开始我就不想改 Markdown 语法或 footnote 的生成方式。

现在文章是这样写的。

正文句子。[^source]

[^source]: 资料说明和链接

这个方式应该保留。

从写作角度看,我使用接近 Markdown 标准的语法,Jekyll 构建时由 Kramdown 生成脚注 HTML。底部的参考资料区域也继续保留。如果连这个结构都替换掉,就要影响既有文章和翻译文章。

所以这次工作的标准很简单。

写作方式保持不变。
Kramdown 生成的底部脚注也保持不变。
只改变正文脚注链接的显示和点击行为。

也就是说,保留原始数据和 fallback,只改善阅读体验。

让脚注编号看起来像 [1]

首先改 CSS。

Kramdown 会给正文脚注链接加上a.footnote类。我把这个链接做成小的 inline-flex 按钮,再用::before::after加上方括号。

结果正文里不再只是一个数字,而是这样显示。

[1] [2] [3]

手指可点击的区域也稍微变大了。

如果做成很醒目的按钮,会破坏正文节奏。但如果还像以前那样只是一个小数字,又很难点击。所以只加了很薄的边框和背景,同时让字号保持比正文小。

这个博客有亮色模式和暗色模式,所以颜色没有硬编码,而是配合既有 Sass 变量。

$primary-color
$background-color
$border-color
$text-color

这个博客已经在亮色和暗色 skin 之后统一加载customOverride.scss。所以我没有直接改主题原始文件,而是在_sass/custom/customOverride.scss里添加脚注样式。

点击时生成弹出层

下一步是 JavaScript。

以前所有#hash链接都挂了 SmoothScroll。脚注链接归根结底也是指向#fn:...的内部链接,所以点击后会平滑地向页面下方移动。

这次只先拦截正文里的脚注链接。

目标是这个。

.page__content a.footnote[href^="#fn"]

点击后,脚本会阻止原来的 hash 移动,找到底部脚注列表里已经渲染好的内容并复制出来。底部脚注里包含返回正文的reversefootnote链接,但在弹出层里不需要,所以去掉。

流程是这样的。

点击正文脚注
-> 从 href 读取 target id
-> 找到底部 footnote li
-> clone 内容
-> 移除 reversefootnote
-> 插入弹出层
-> 计算脚注链接附近的位置

因为不改变 hash,URL 不会变乱。页面也不会跳到最底部。

关闭方式做了三种。

再次点击同一个脚注
点击弹出层外部
Esc 或关闭按钮

为了键盘使用,也加了aria-haspopup="dialog"aria-expanded。弹出层本身使用role="dialog"。这还谈不上是完美的无障碍组件,但至少比一个没有语义的浮动 div 更好。

让它在手机上不跑出屏幕

脚注弹出层的位置计算很重要。

显示在正文链接正下方很自然,但在屏幕右侧边缘或手机宽度下,很容易溢出。

所以定位时强制保留 viewport 内侧 margin。

左侧最少 12px
右侧也最少 12px
下方空间不足时显示到上方
仍然不足时 clamp 到 viewport 内

弹出层宽度也不是固定值,而是这样设置。

width: min(30rem, calc(100vw - 1.5rem));

在桌面端不会过宽,在手机端不会比屏幕更宽。

为了应对较长脚注,也加了max-heightoverflow: auto。外部文章标题或链接很长时,弹出层也不至于盖住整个屏幕。

压缩文件也一起更新

这个博客里,assets/js/_main.js是源文件,实际部署时读取的是assets/js/main.min.js

所以改完 JS 后,用 Rake 任务重新生成了压缩文件和 source map。

bundle exec rake js

如果漏掉这一步,本地源文件看起来已经修好,但实际网站仍可能继续输出旧 JS。这类工作必须同时检查源文件和部署文件。

确认过的内容

确认是这样做的。

node --check assets/js/_main.js
bundle exec rake js
bundle exec jekyll build

然后通过本地静态服务器打开一篇脚注很多的实际文章确认。

确认内容如下。

脚注链接是否显示成 [1] 形式
点击后 URL hash 是否不变
是否不会移动到底部参考资料区
弹出层是否出现
弹出层里是否包含底部脚注内容
手机宽度下弹出层是否仍在屏幕内

桌面端上,底部脚注位于文档很下方,但点击脚注后滚动位置仍停留在正文附近。手机宽度下,弹出层也在屏幕内。

功能很小,但阅读感觉差很多

这次工作不是很大的功能。

没有数据模型,没有路由,也没有新页面。只是让既有脚注链接更容易看、点击时弹出一个层而已。

但阅读感觉确实变了不少。

尤其在事实关系很多的文章里,脚注不是装饰。读者觉得“这句话从哪里来的?”时,应该能马上确认。如果一确认就被扔到文章最底部,然后还要再回到正文,脚注很快就会变成麻烦的东西。

现在可以一边读正文,一边点[1],确认后关掉。

底部的参考资料也仍然保留。想在文章结尾一次性查看资料的人,依旧可以看最底部。

我想要的就是这个程度。

Markdown 写作方式保持不变,Jekyll/Kramdown 的基本结构也保留,只让阅读者的手指和眼睛少累一点。

博客需要继续积累这种小改进。

留下评论