data-math
Enhance code elements with precompiled MathML rendering. Add data-math to any code element for automatic MathML injection with numbering, copy, and Markdown integration.
Overview
The data-math attribute enhances <code> elements with precompiled MathML. The original LaTeX source stays readable without JavaScript, and when JS runs, it is replaced by rendered MathML.
<code data-math data-mathml="<math display='block'><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>"> x = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a}</code>
How It Works
- Add
data-mathto a<code>element with LaTeX source as its text content - Add
data-mathmlwith the precompiled MathML string - On page load, the script reads
data-mathml, injects a<math>element, and hides the original<code> - Without
data-mathml, the LaTeX source displays as-is — readable fallback with no JS dependency
Attributes
| Attribute | Type | Description |
|---|---|---|
data-math |
token list | Space-separated tokens: inline, numbered, copyable. An empty value defaults to block rendering. |
data-mathml |
string | Precompiled MathML string to inject. Without this, the element shows the raw LaTeX source. |
data-math-state |
string | Set automatically: "rendered" when MathML injected, "source" when showing raw LaTeX. |
data-math-init |
boolean | Set automatically to prevent double-binding. Do not set manually. |
Tokens
| Token | Description |
|---|---|
inline |
Renders inline math, wrapping in a <span> instead of a <div>. |
numbered |
Auto-increments the equation counter and displays a number. Registers in window.VBMath.equations if the element has an id. |
copyable |
Clicking the rendered math copies the original LaTeX source to the clipboard with a screen reader announcement. |
Inline Math
Use the inline token for math that flows within paragraph text.
The area is
\pi r^2
.
<p>The area is <code data-math="inline" data-mathml="<math><mi>π</mi><msup><mi>r</mi><mn>2</mn></msup></math>"> \pi r^2 </code>.</p>
Numbered Equations
Combine numbered with an id for linkable, numbered equations.
E = mc^2
<code data-math="numbered" id="eq-energy" data-mathml="<math display='block'><mi>E</mi><mo>=</mo><mi>m</mi><msup><mi>c</mi><mn>2</mn></msup></math>"> E = mc^2</code> <p>See <a href="#eq-energy">Equation 1</a>.</p>
Copyable Math
The copyable token adds a click-to-copy interaction. Clicking copies the LaTeX source to the clipboard and announces it to screen readers.
\int_0^\infty e^{-x^2} dx = \frac{\sqrt{\pi}}{2}
<code data-math="copyable" data-mathml="<math display='block'><msubsup><mo>∫</mo><mn>0</mn><mo>∞</mo></msubsup><msup><mi>e</mi><mrow><mo>-</mo><msup><mi>x</mi><mn>2</mn></msup></mrow></msup><mi>d</mi><mi>x</mi><mo>=</mo><mfrac><msqrt><mi>π</mi></msqrt><mn>2</mn></mfrac></math>"> \int_0^\infty e^{-x^2} dx = \frac{\sqrt{\pi}}{2}</code>
Markdown Integration
Markdown processors emit code.language-math for fenced math blocks. The enhancement script auto-detects these — no extra configuration needed.
```mathx = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a}```
This produces the standard HTML output:
<pre><code class="language-math"> x = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a}</code></pre>
The code.language-math selector is matched automatically alongside [data-math]. For precompiled MathML, add data-mathml to the element at build time via a Remark or Markdown-it plugin.
Events
| Event | Detail | Description |
|---|---|---|
math:rendered |
{ latex, inline, number } |
Fired after MathML is injected. latex is the source text, inline is a boolean, number is the equation number (or null). |
const el = document.querySelector('[data-math]'); el.addEventListener('math:rendered', (e) => { console.log('LaTeX:', e.detail.latex); console.log('Inline:', e.detail.inline); console.log('Number:', e.detail.number);});
Progressive Enhancement
Without data-mathml, the LaTeX source displays as a readable <code> block. This is the no-JS fallback:
<code data-math>E = mc^2</code><!-- Without data-mathml, the LaTeX source displays as readable code -->
The element receives data-math-state="source" so you can style the fallback state differently if needed.
Dynamic Content
Elements added to the DOM after page load are automatically enhanced via a MutationObserver. No manual initialization needed.
const code = document.createElement('code');code.dataset.math = 'inline';code.dataset.mathml = '<math><mi>x</mi></math>';code.textContent = 'x';document.body.appendChild(code);// Auto-enhanced via MutationObserver/code-block
Accessibility
- The injected
<math>element is natively understood by screen readers (VoiceOver, NVDA) - The original LaTeX source is preserved in the DOM as hidden fallback content
- Copy confirmation uses
aria-live="polite"for screen reader announcements - Numbered equations are linkable via
idand standard<a href>