优化MathJax公式引用跳转偏移

在 Hexo + Fluid 主题里,如果你开启了 MathJax,并且在文章里用 \label / \eqref 做公式编号与引用,经常会遇到一个体验问题:点击引用跳转后,落点总是偏下,导致目标公式被顶部导航栏遮住,或者需要再往上滚一下才能看到。

这篇文章记录一次「不改主题源码、只用 Fluid 的自定义注入能力」的修复过程:让标题锚点MathJax 公式引用锚点都能更准确地跳转到可视位置。

现象与原因

1) 普通锚点:被 fixed navbar 遮住

Fluid 的导航栏是固定在顶部的(fixed / sticky),浏览器默认的锚点跳转会把目标元素滚到视口顶部,结果目标内容被导航栏盖住。

这种问题通常用 CSS 的 scroll-padding-top / scroll-margin-top 就能解决。

2) MathJax 公式引用:跳到了“编号单元格”,不是“公式块”

更麻烦的是 \eqref{...}:MathJax 生成的链接会指向形如:

  • #mjx-eqn%3Aeq%3Aeinstein2(URL 编码后)

而这个 id 通常挂在 公式右侧编号那一格(例如 <mjx-mtd id="mjx-eqn:eq:einstein2">),而不是挂在整个公式容器(<mjx-container>)上。

对于较高/多行公式,滚动到“编号单元格”的位置,视觉上就会像「跳过头」:你看到的是编号附近,而不是公式顶部。

所以仅靠 *:target { scroll-margin-top: ... } 仍可能不准,需要额外把落点校正到 对应的 <mjx-container>

方案:CSS 统一偏移 + JS 专门修正 MathJax 锚点

实现思路:

  1. 用 CSS 解决大多数锚点场景(标题、手写 <a id=...> 等),让浏览器原生滚动就带 offset。
  2. mjx-eqn... 这种 MathJax 锚点,监听 hashchange,把滚动目标从“编号单元格”改为最近的 <mjx-container>,并按导航栏高度做偏移。

1) 添加全局锚点偏移 CSS

新建文件:source/custom/scroll-offset.css

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
:root {
/* 预留给顶部导航栏的高度(可按需调整) */
--anchor-offset: 96px;
}

html {
scroll-padding-top: var(--anchor-offset);
}

*:target {
scroll-margin-top: var(--anchor-offset);
}

/* MathJax 公式编号/标签的锚点(id 类似 mjx-eqn:eq:xxx) */
*[id^="mjx-eqn"] {
scroll-margin-top: var(--anchor-offset);
}

说明:

  • html { scroll-padding-top }:影响浏览器对“锚点滚到顶部”的默认行为。
  • *:target { scroll-margin-top }:对命中的目标元素额外设置上边距,兼容更多情况。

2) 添加 MathJax 锚点跳转校正 JS

新建文件:source/custom/mathjax-anchor-fix.js

核心逻辑:

  • 如果 hash 以 mjx-eqn 开头:找到那个 id 对应的元素(通常是 mjx-mtd),再向上找最近的 <mjx-container>,滚到它的顶部。
  • 偏移量使用 #navbar 的实际高度(避免你手动估算)。
  • 为了应对 MathJax typeset 和字体加载造成的布局变化,短时间内重复校正几次,并在 MathJax.startup.promise 完成后再跑一次。

(代码已在本仓库添加,文件名如上,不再重复贴全文。)

3) 在 Fluid 配置中注入自定义资源

编辑 _config.fluid.yml,把自定义文件加到 custom_css / custom_js

1
2
3
4
5
6
7
custom_js:
- /custom/ReadingProgress/ReadingProgress.js
- /custom/mathjax-anchor-fix.js

custom_css:
- /custom/ReadingProgress/ReadingProgress.css
- /custom/scroll-offset.css

注意:

  • 路径是相对 source/ 的站点根路径(例如 source/custom/scroll-offset.css 对应 /custom/scroll-offset.css)。
  • 修改 _config.fluid.yml 后,通常需要重启本地预览(hexo server)。

4) 重新生成并验证

1
2
3
npm run build
# 或者预览
npm run server

建议用一个最小用例验证(本仓库已有类似测试文章):

1
2
3
\begin{equation}\label{eq:test}
E = mc^2
\end{equation}

然后在正文里写:

1
如式 \eqref{eq:test} 所示。

点击引用 (1) 后应能直接看到公式(不需要再手动往上滚)。

可调参数与排错思路

  • 如果仍被遮住:把 source/custom/scroll-offset.css 里的 --anchor-offset 调大一点。
  • 如果只对 \eqref 不准:打开浏览器控制台看 location.hash,确认是否是 #mjx-eqn... 形式;如果主题或 MathJax 配置改变导致 DOM 结构变化,可以把 JS 里“找最近 <mjx-container>”那段改成更贴合你页面结构的选择器。

优化MathJax公式引用跳转偏移
http://sakura.lsk.icu/2025/12/18/优化日记/1.优化Hexo-Fluid主题-修复MathJax公式引用跳转偏移/
作者
Sakura
发布于
2025年12月18日
许可协议