# Displaying math in HTML

As of right now, asking a search engine

"How do I put mathematical equations on a web page?"

gets you a mixture of incomplete, outdated, and misleading advice. The advice ususally boils down to "put LaTeX expressions on your website, then ask each reader to compile the LaTeX to renderable HTML (using a big pile of javascript) every time they visit." Thankfully, as of 2023, this is no longer necessary.

This post in short: Compile math to MathML on the server. For the reader, MathML is lightweight and (now) well-supported. For the writer, generating MathML from LaTeX expressions [1] is not too hard to do. The alternatives are Katex and MathJax.

## MathML

If you’d like to try it out, the following should show up as ${g}^{x}$ in a browser without any additional CSS or javascript files:

<!doctype html> <html> <math> <msup> <mi>g</mi> <mi>x</mi> </msup> </math> </html>

The MathML standard has been around since 1998. Unfortunately, that doesn’t mean the reader’s browser could actually render your MathML until recently. Firefox and WebKit always had support for MathML, but Chromium didn’t support it consistently until early 2023. [2]

Many existing websites, including large ones like StackExchange, decided how to typeset math a long time ago. When writers of new websites make this decision, I can only hope they don’t listen to the first few results on Google. Let’s take a look at the results I get from the query at the top of this page.

### What does Google say?

The first clickable link Google produces was fun to read, but might be the most outdated possible page on the subject: a November 1993 recommendation to render math by converting LaTeX to bitmap images, and embedding them in the page. (If you look closer, this document is actually part of a "HTML+" proposal, meant to compete with HTML before it was a standard).

The second clickable link (archived today) is a Stack Overflow post which must be responsible for countless wasted CPU cycles. The top answer makes the right recommendation (MathJax) at the time (2009), but ignores the single greatest reason for the recommendation (it actually works in most browsers), makes some dubious claims (MathJax takes "a fraction of a second"), then tops it off with a misinformed footnote that has likely scared writers from using MathML for life:

"MathML is ridiculous. It’s neither human-readable nor human-writable (the quadratic equation takes 800 characters - it’s 50 in Tex). It’s just another pointless XML language. Thankfully, it’s obsolete before most browsers support it. It doesn’t even look as good as Tex or Mathjax’s HTML-CSS!"

As a reminder that competence doesn’t come with confidence, let’s dissect this.

Comparing the readability/writability of LaTeX and MathML is a mistake here; one is the input and one is the machine-generated output. (I wouldn’t even call MathML far from being human-readable or writable, but that is beside the point.)

Even if "the quadratic equation takes 800 characters", I don’t think that sending 200,000 characters of javascript, from a CDN you need to trust, to be executed on the reader’s computer, once every time they want to see your quadratic equation, is prettier.

The link provided with the 800-character claim is (1) longer than it needs to be, and (2) not renderable in any browser. It uses content MathML, which falls outside of the web-renderable MathML subset, "MathML Core". It encodes the semantics of the math; you could theoretically use it for calculations. Here is a quadratic equation in about 350 characters of MathML (Core): $$x=\frac{-b\pm \sqrt{{b}^{2}-4ac}}{2a}$$

Aiju (author of 800-character claim website) makes some angry comments, but I can sympathize. [3] I assume they think it’s an ugly representation of the equation’s semantics, where an alternative representation is something like ’(let ((d (sqrt (- (expt b 2) (* 4 a c))))) (cons (/ (- d b) (* 2 a)) (/ (- (+ d b)) (* 2 a)))). The Stack Overflow answerer misunderstands this, linking to Aiju’s site to argue against presenting math using MathML, which is like arguing that the bytes in a PDF are unreadable and too numerous.

### That’s it? MathML wins? (no)

While this post mainly exists to encourage server-side MathML generation (or even writing MathML by hand) over the other methods, picking any method and getting your web page online is better than procrastinating for another year. Hence the other methods are described below. I also can’t find a comparison of the available methods anywhere, so hopefully this will serve as one.

In summary: KaTeX and MathJax are generally worse for the reader, but can be easier to implement for the writer.

## Javascript options

### MathJax

MathJax is a wonderful project. It is a javascript library that converts input (usually LaTeX) to something renderable, either MathML or HTML styled with CSS. Its first release was in 2010, way before it was easy to put math in a web page. Its front page boasts "no more setup for readers," which hints at the terrible situation they were fixing.

If you are writing raw HTML, MathJax wins at being easy to set up (documentation here):

<!doctype html> <html> <script type="text/javascript" id="MathJax-script" async src="insert URL here"> </script> <p>$$g^x$$</p> </html>

The first downside is visible in the script tag above: the javascript needs to get to the reader, but where will it come from? Most sources say to serve it from a CDN you don’t control. The obvious problem is made obvious when the very top stack overflow answer on the matter (the same one as above) recommends using a CDN that shut down in 2017. Instead, you can host the script wherever you host the website, as it’s really not that much trouble.

The second (and main) downside of MathJax is the slowness of running the javascript. It’s bad enough that, even with a fancy modern computer, I don’t feel the need to take measurements (though I should, TODO). At this point, visitors are probably used to watching all the elements on math.stackexchange.com jump around for a few seconds as things load.

MathJax has many knobs and dials. The speed likely varies for each configuration and version.

### Katex

Katex is also a wonderful project, similar to MathJax, but with the simple goal of being faster. Setting it up is about as easy as with MathJax, and it suffers from the same issues. No matter how fast it is compared to MathJax, running your LaTeX through a javascript machine will be strictly slower than having the output of the machine ready.

### Javascript on the server

It’s possible to run MathJax or Katex on your server (or website-compiler), although it’s rare in practice, especially so for MathJax. [4] With configuration, you can use either one as a method of generating MathML, or the old HTML+CSS math. This is good, but unless you’re already running javascript on the server, using javascript here makes things more difficult than they need to be, and better solutions are below.

## MathML-generating software

This section is especially susceptible to going out of date.

latexmlmath is a command-line utility that converts LaTeX math to MathML. It is slow, but this slowness happens once per compilation instead of once per page visit. You can try it with

latexmlmath -- '\left\{\frac{a}{b}\right\}'

In my experience, it generates the best-looking math.

Pandoc can produce MathML output. For a file like

<!doctype html> <html> <p>$$\left\{\frac{a}{b}\right\}$$</p> </html>

you can produce a MathML expression using

pandoc --mathml --from html+tex_math_dollars+raw_html --to html input.html -o output.html

Pandoc is already a part of many static site generators, and is much faster than latexmlmath.

## Some comparisons

### Accessibility

There are screen readers that support reading MathML. MathJax puts MathML somewhere in the document, so their documentation says it should be readable by the same programs. Katex, by default, generates MathML in a 1-pixel-tall div above the visible equation for accessibility purposes, which is amusing.

MathJax seems to have some fancier accessibility features and plugins. I am not sure I would consider these to make up for the slowness issue.

Of course, you can put LaTeX annotations on math elements, and this is done automatically by the tools mentioned above:

<math xmlns="http://www.w3.org/1998/Math/MathML" alttext="g^x"> <msup> <mi>g</mi> <mi>x</mi> </msup> </math>

### Speed

From fastest to slowest:

MathML < Katex ~= MathJax 3 < MathJax 2.

these measurements being unscientific, based on what people say on the internet and the noticable lag I’ve seen.

### Browser compatibility

MathML (Core) is supported by all modern browsers as of today. MathJax 3 and Katex support these plus IE 11 and old versions of Chrome; MathJax 2 supports older versions of IE too.

## Conclusion: thank you Igalia

It only took 25 years, but nice-looking math in the browser is finally possible, easy without javascript, and widely available. I won’t philosophize about the value this brings to the world in comparison to most new software features you hear about; that is left as an exercise to the reader.

We don’t need to be limited to LaTeX here (typst and AsciiMath are good options), just no software exists yet. I am tempted to write a typst-to-MathML compiler, but will wait until either (1) I’m more familiar with both syntaxes, (2) someone else does it before I get to it, or (3) I get frustrated enough. | |

Browser support for MathML was made easier in 2021 with the release of the MathML Core specification. Roughly, this is the subset of MathML relevant to visual rendering on the web, and a superset of the implementation details. The full MathML specification is larger for rendering elsewhere (e.g. EPUB) and includes "content MathML" (semantics-focused). Since rendering math on the web is what this post is about, you can take my mentions of MathML to mean MathML Core. | |

If you are a person in computing within a certain age range, I will be understanding with your lasting XML-related trauma. | |

Later, I found two great blog posts that get everything right other than being written in 2020: Math Rendering is Wrong and Rendering Mathematics on the Back End. The post author Daniel spells out the argument against client-side math rendering, which I have not done in this post, but agree with completely. They also show the kind of setup you would need for server-side math rendering in 2020. |