elvhack
← 全部文章

在网页上做 Tufte 式旁注

宽屏时把脚注挪到正文右侧的页边,和正文里的标号对齐;窄屏退回文末脚注;读屏器始终读到原来的脚注。

发布
阅读
约 1 分钟
信号
SIG-749A · moire

Edward Tufte 的书有一个让人难忘的版式:注释不在页脚,而在正文旁边的宽页边里,眼睛一偏就能看到1。这个站的文章页在宽屏上也这么做。

布局

屏幕宽于 1280px 时,文章页是三栏:左边目录,中间正文,右边是一条空的“旁注栏”。旁注栏和正文在同一个网格行里,所以它们的顶边天然对齐。

把脚注搬过去

Markdown 生成的脚注是标准结构:正文里一个 <a data-footnote-ref>,文末一个 <section class="footnotes">。脚本做三件事:

  1. 找到每个标号对应的脚注条目,克隆一份,去掉“返回正文”的链接,放进旁注栏。
  2. 计算标号相对于旁注栏顶部的位置,把旁注平移到同一高度。
  3. 如果上一条旁注还没结束,就往下推,保证互不重叠。
let floor = 0;
for (const { ref, note } of notes) {
  const top = Math.max(ref.getBoundingClientRect().top - base - 3, floor);
  note.style.transform = `translateY(${Math.round(top)}px)`;
  floor = top + note.offsetHeight + 18;
}

图片加载、字体加载、窗口缩放都会改变正文的排版,所以用 ResizeObserver 盯着正文,变化时重新排一遍。

照顾读屏器

旁注是给眼睛看的复制品,所以标记为 aria-hidden。原来的脚注并没有删掉,只是在宽屏下用视觉隐藏的方式藏起来,读屏器依然能按顺序读到它们2。

顺带的排版细节

  • 标题用思源宋体,只加载 600 一个字重,并按 unicode-range 切成一百多片,浏览器只下载页面上真正用到的字。
  • text-autospace 会在中文和英文、数字之间自动留出一点空隙,作者不用手动敲空格。

Footnotes

  1. 网页上把这件事做得最好的大概是 gwern.net。 ↩

  2. 宽屏下点击正文里的标号也不会跳到文末,而是让对应的旁注闪一下。 ↩