MathML全称为Mathematical Markup Language,是W3C为描述数学符号和结构制定的一种基于XML的标记语言。它把公式拆解为树状语义节点,例如分数、根号、上下标、矩阵等都有对应的标签,浏览器或辅助技术可以据此理解公式含义,而不仅仅是显示一张图。对于需要在网页中严谨呈现数学内容的场景,比如教育平台、学术论文库、技术文档站,MathML提供了一套标准化的解决方案。
MathML的基本结构
MathML主要分为两部分:Presentation MathML负责外观排版,Content MathML负责数学语义。日常在网页上显示公式,通常用Presentation MathML就够了。一个最外层是<math>标签,里面嵌套如<mfrac>表示分数、<msqrt>表示根号、<msup>表示上标等。
比如要写a除以b,结构就是<mfrac>包两个子元素,第一个是分子,第二个是分母。这种写法让屏幕阅读器能读出“a分之b”,而不是一堆乱码。下面是一段静态HTML中使用MathML的示例,注意所有标签都以文本形式书写并转义:
<math xmlns="http://www.w3.org/1998/Math/MathML">
<mfrac>
<mi>a</mi>
<mi>b</mi>
</mfrac>
</math>
上面的代码在支持MathML的浏览器里会渲染出一个正规的分数样式。Presentation MathML的标签都很直观:<mi>是标识符,<mn>是数字,<mo>是运算符。合理组合它们就能拼出复杂公式。
在网页中直接嵌入MathML
最简单的方式就是把<math>片段直接写进HTML文档。由于HTML5已经将MathML纳入规范,在Chrome、Firefox、Safari等现代浏览器中,不需要引入任何JavaScript库即可显示。你只需要保证外层页面是HTML5文档类型,并且MathML标签书写正确。
下面示例展示一个二次方程求根的常用公式,用MathML完整写出来。可以看到根号嵌套分数,分数里又有上标,这种层级结构用标签嵌套自然表达:
<math xmlns="http://www.w3.org/1998/Math/MathML">
<mi>x</mi>
<mo>=</mo>
<mfrac>
<mrow>
<mo>-</mo>
<mi>b</mi>
<mo>±</mo>
<msqrt>
<msup><mi>b</mi><mn>2</mn></msup>
<mo>-</mo>
<mn>4</mn>
<mi>a</mi>
<mi>c</mi>
</msqrt>
</mrow>
<mrow>
<mn>2</mn>
<mi>a</mi>
</mrow>
</mfrac>
</math>
这种写法的优点是稳定、轻量,不依赖网络请求。缺点是手写复杂公式比较繁琐,且老版本IE完全不支持,如果需要兼容非常旧的环境,就要配合Polyfill方案。
用JavaScript动态生成MathML
当公式由后端数据或用户输入决定时,可以用脚本创建MathML节点。由于MathML是XML命名空间下的元素,必须用createElementNS来建节点,而不能用普通的createElement,否则浏览器不会按数学标签解析。
下面代码演示如何用JS动态拼一个x的平方并插入页面。注意命名空间字符串必须写对,子元素也要用同一命名空间:
const ns = 'http://www.w3.org/1998/Math/MathML'; const math = document.createElementNS(ns, 'math'); const msup = document.createElementNS(ns, 'msup'); const mi = document.createElementNS(ns, 'mi'); mi.textContent = 'x'; const mn = document.createElementNS(ns, 'mn'); mn.textContent = '2'; msup.appendChild(mi); msup.appendChild(mn); math.appendChild(msup); document.body.appendChild(math);
这种方式适合公式编辑器、在线题库等场景。它的可控性强,但开发者要小心拼错标签名,因为写错后浏览器可能静默不渲染。建议在开发阶段打开控制台检查生成的DOM结构。
兼容性处理与替代方案
虽然主流浏览器已支持MathML,但有些嵌入式WebView或旧系统仍然不支持。此时可引入MathJax或KaTeX作为降级方案:它们能识别LaTeX语法并输出为MathML或SVG。另一种思路是服务端把公式转成图片,但那样会丧失语义和清晰度。
如果决定用MathML为主、库为辅,可以先检测document.createElementNS能否创建<math>且被识别,不支持时再加载转换库。这样既照顾现代体验,也不放弃老旧用户。下表列出几种渲染方式的差异:
| 方式 | 优点 | 缺点 |
|---|---|---|
| 原生MathML | 无需脚本、语义好 | 旧浏览器不支持 |
| MathJax | 兼容广、支持LaTeX | 体积大、需加载 |
| 图片公式 | 任何环境可见 | 无语义、放大模糊 |
总体来看,新项目优先采用原生MathML,既符合Web标准,也让数学内容更易被机器和消费端理解。遇到兼容死角再局部补强,才是稳妥的工程做法。