Is it possible to dynamically change the font MathJax v4 uses?

7 views
Skip to first unread message

Christian Lawson-Perfect

unread,
Jan 13, 2026, 6:43:42 AMJan 13
to MathJax Users
Hi,
I've had a quick look at the documentation but not the code so I apologise if there's an obvious answer to this.
I'd like to offer users a choice of fonts used for maths in the page. The documentation says to put your chosen font in the MathJax config. Is there a way of modifying that after the page has loaded, so I can then re-render all the maths in the page with a different font?

Davide Cervone

unread,
Jan 14, 2026, 2:08:01 PM (14 days ago) Jan 14
to mathja...@googlegroups.com
Christian:

Font switching is not really a supposed use case, but it can be done.  Here is a document that illustrates how:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>Switch Fonts</title>
  <script>
  async function setFont(select) {
    select.disabled = true;
    const font = select.value;
    MathJax.config.output.font = font;
    MathJax.config.loader.paths[font] = `https://cdn.jsdelivr.net/npm/@mathjax/${font}-font@4`;
    const doc = MathJax.startup.document;
    const promises = [];
    for (const name of Object.keys(doc.menu.jax)) {
      if (!doc.menu.jax[name]) continue;
      const jax = name.toLowerCase();
      MathJax.config[jax].font = font;
      promises.push(MathJax.loader.load(`[${font}]/${jax}`).then(() => {
        const fontData = Object.values(MathJax._.output.fonts[font][`${jax}_ts`])[0];
        MathJax.config[jax].dynamicPrefix = `[${font}]/${jax}/dynamic`;
        MathJax.config[jax].fontData = fontData;
        if (jax === 'chtml') {
          MathJax.config.chtml.fontURL = `https://cdn.jsdelivr.net/npm/@mathjax/${font}-font@4/chtml/woff2`;
        }
        for (const extension of fontData.dynamicExtensions.keys()) {
          MathJax._.output.fonts[extension]?.[jax]?.install?.();
        }
        const JAX = new doc.menu.jax[name].constructor(MathJax.config[jax]);
        JAX.setAdaptor(doc.adaptor);
        doc.menu.jax[name] = JAX;
      }));
    }
    await Promise.all(promises);
    doc.outputJax = doc.menu.jax[doc.outputJax.name];
    await doc.rerenderPromise(MathJax._.core.MathItem.STATE.METRICS);
    select.disabled = false;
  }
  </script>
</head>
<body>


If \(a \ne 0\), then \(ax^2 + bx + c = 0\) has two solutions,
\[x = {-b \pm \sqrt{b^2-4ac} \over 2a}.\]


<select id="font" onchange="setFont(this)">
<option>mathjax-asana</option>
<option>mathjax-bonum</option>
<option>mathjax-dejavu</option>
<option>mathjax-fira</option>
<option>mathjax-modern</option>
<option selected>mathjax-newcm</option>
<option>mathjax-pagella</option>
<option>mathjax-schola</option>
<option>mathjax-stix2</option>
<option>mathjax-termes</option>
<option>mathjax-tex</option>
</select>

<script>
document.querySelector('#font').value = 'mathjax-newcm';
</script>

</body>
</html>

I'm not going to go into the details of how this works, but in order to handle changing renderer as well as fonts, you need to deal with the potential of loading the font for both CHTML and SVG renderers.  That way, if you switch renderers then switch fonts, then switch renders back to the original, the changed font will be used, not the font that previously in use with that renderer.  

First, the font component is loaded, and then work done here to set up the output configurations properly for the font (usually handled by the output jax when its component is first loaded, but that won't occur a second time).  Then a new instance of the output jax is created using the updated configuration and it is hooked into the menu cache.  This is done for any output jax that have been loaded already.  Finally, the new output jax used to replace the current one, and the document is re-rendered starting from the step that gets the metrics for the surroundings of the expressions on the page (as some of those depend on the font em- and ex-sizes, so need to be updated for the new font).

In any case, that's the basic idea.  See if that works for you.

Davide


--
You received this message because you are subscribed to the Google Groups "MathJax Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mathjax-user...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/mathjax-users/CAEMHSOiPF2EmHS0WnZvAmutcDfzKJ52EmtxGNoUusufih7eRiw%40mail.gmail.com.

Reply all
Reply to author
Forward
0 new messages