A Technical Introducition to MathML Core for Writing Mathematics on the Web

- Programming, Mathematics

Floating mathematical formulas

Thanks to recent efforts, all major web browsers currently support MathML Core, a subset of MathML focused on important presentation markup, to support mathematics on the web. As of this writing, the MathML Core specifications are still not finalized, but given its strong origins and support, it can be used right now by web developers.

While the full version of MathML is relatively complex, MathML Core keeps almost all of its capabilities while being simple enough to directly code and read it without relying on external tools and renderers. In fact, I would highly discourage this practice, as said tools tend to generate valid code that may look correct but generally are unnecessarily complex and hide accessibility or other issues. Classic tools like TeX, LaTeX, MathType and MathJax are therefore no longer relevant in MathML Core.

Before writing this blog post, I took the time to completely re-write all of the mathematics on my website in MathML Core to fully understand its strengths and weaknesses, so feel free to browse my previous blog posts for examples such as the one where I explain how deep learning AI works.

The following is a technical introduction to MathML Core which assumes you have a basic understanding of Unicode and are familiar with general web development in HTML and CSS. I have deliberately omitted several MathML Core elements, attributes and CSS properties to focus exclusively on writing mathematical expressions as efficiently as possible.

Inheritance from other web specifications

HTML

Text in MathML Core is normal HTML flow content, and can therefore embed additional HTML and/or SVG elements in it.

CSS

MathML Core supports all normal CSS properties from HTML.

MathML Core implements additional CSS properties and/or values specific to its elements, but these are out of scope of this introduction.

Scripts

MathML Core is fully-compatible with normal client-side scripting.

Global attributes

class, data-, dir, id, nonce, on event handlers, style, tabindex attributes: Behaves the same way as for HTML elements.

displaystyle attribute: By default, script sub-expressions are always rendered in compact style. This attribute overrides whether the expression should be rendered in normal or compact style. Possible values are true for normal style, and false for compact style.

scriptlevel attribute: By default, a script sub-expression will appear slightly smaller than its direct parent if said direct parent is in compact style. This attribute overrides this behavior. Its value should be an integer. If the integer starts with a sign (+ or -), the script level change is relative to its parent, otherwise the change is absolute, with 0 being the default top-level.

Important elements

<math>

The top-level element for MathML Core expressions. Note that there is no need to apply the xmlns attribute on it, as MathML Core elements are recognized by HTML as foreign elements.

Content: A MathML Core expression.

display attribute: Determines if the mathematical expression should be rendered in compact style as inline text, or in normal style as a block. Possible values are inline (default) and block. Note that while this attribute is linked to the display CSS property, it is not equivalent.

<mtext>

Arbitrary text, generally for commentary.

Content: Normal text.

<mi>

An identifier, such as a function, variable or constant name, or a placeholder.

Content: Normal text.

mathvariant attribute: By default, if this element contains a single letter, it will be rendered in italic. If this attribute is present and set to normal, this behavior will not be automatically applied.

<mn>

A numeric literal. It doesn't matter if the contents is written in decimal, hexadecimal, binary, Japanese numerals, Roman numerals, plain English or some other representation, as long as said representation matches a numeral system.

Content: Normal text. Generally however, this element should contain a nonnegative rational number in positional notation. Base 10 should also generally be used unless another base is more appropriate in context.

<mo>

This represents any of the following:

The default rendering of this element is complex and changes depending on its content and positioning. For example, an <mo> containing a single left curly bracket will be automatically stretched and will not have blank spaces around it is the first element in a group of multiple elements.

Content: Normal text. Generally however, this element should contain a single character.

Note that this element has many attributes specific to it to modify its rendering, but they are out of scope of this introduction, with the exception of an issue related to calculus described in the Workarounds section below.

<ms>

A string literal, as used in programming languages. This should be used only when the contents of this element is part of the actual mathematical expression.

Content: Normal text. Quotes should generally be included.

<mrow>

Groups elements that are not implicitly grouped by another element, for sub-expressions. Proper grouping allows for better automatic rendering, including automatic line breaking when the available width is insufficient.

Content: A MathML Core expression.

<mfrac>

A fraction or fraction-like object, such as the inside of a binomial coefficient.

Content: The first element is the numerator, and the second element is the denominator.

linethickness attribute: Changes the thickness of the line between the numerator and the denominator. Possible values are any valid CSS length or percentage. If this attribute is set to 0, no line is drawn and the element behaves similarly to a 1x2 table.

<msqrt>

A radical without an index, generally used for square roots.

Content: The base of the root.

<mroot>

A radical with an index, such as a cube root.

Content: The first element is the base of the root, and the second element is the index of the root.

<msub>

An expression with a subscript, such as a number in a non-decimal base.

Content: The first element is the base, and the second element is the subscript.

<msup>

An expression with a superscript, such as a squared number.

Content: The first element is the base, and the second element is the subscript.

<msubsup>

An expression with both a subscript and a superscript, such as a derivative in Lagrange's notation of a numbered variable.

Content: The first element is the base, the second element is the subscript, and the third element is the superscript.

<munder>

An expression with an underscript, such as a limit.

Content: The first element is the base, and the second element is the underscript.

<mover>

An expression with an overscript, such as a complex conjugate.

Content: The first element is the base, and the second element is the overscript.

<munderover>

An expression with both an underscript and overscript, such as a sum with capital-sigma notation.

Content: The first element is the base, the second element is the underscript, and the third element is the overscript.

<mmultiscripts>

An expression with an arbitrary number of subscripts and superscripts including prescripts, such as a tensor.

Content: The first element is the base, and the following elements must be pairs of one subscript and one superscript, in that order. The <mprescripts> element can optionally be added as a separator before or between a pair to indicate that the following pairs are prescripts. Pairs on each side of the separator must be added in reading order. If a pair does not require a corresponding subscript or superscript, an empty <mrow> should be used as a placeholder.

<mprescripts>

A separator for the <mmultiscripts> element. See its description for details.

Content: Should be empty.

<mtable>

A table of mathematical expressions, such as the inside of a matrix. Their format are similar to HTML <table> elements.

Content: <mtr> elements.

<mtr>

A row of mathematical expressions.

Content: <mtd> elements.

<mtd>

A cell containing a mathematical expression.

Content: A MathML Core expression.

columnspan, rowspan attributes: Behaves the same way as for <td> in HTML.

Tricky characters and typefacing

Obscure mathematical operators and symbols

If a specific mathematical character is hard to find via a search engine or other means, I recommend looking at the Mathematical operators and symbols in Unicode article on Wikipedia to find any specific one you may need.

Letter styles

Identifiers in a special style, such as bold, italic or double-struck, should generally directly use the character for these styles instead of applying styles via CSS. I recommend consulting the Mathematical Alphanumeric Symbols article on Wikipedia to determine which character correspond to the desired style for Latin and Greek letters, especially because the corresponding Unicode code points may not be in the expected order due to historical reasons.

One notable exception is when automatic italic is applied. See the description for the <mi> element for details.

Non-standard character references

HTML and MathML contains the following character references that can be used as a substitute for the normal character:

Problem is, unlike what the name of these references suggest, these are not standard ways to write derivatives, Euler's number or the imaginary unit. These references appear to have been inherited from the Wolfram Language back when the original version of MathML was originally created instead.

According to ISO 80000-2, the normal Latin version of these characters (D, d, e and i) should be used in these cases instead.

Invisible characters

There are four invisible characters specifically designed for mathematical expressions:

The purpose of these characters is so that renderers, parsers and blind people can determine what operator is implied between two expressions without additional context. For example, it may be unclear to a reader if an integer followed by a fraction is supposed to represent a mixed fraction or a multiplication.

These invisible characters should always be present in a MathML Core expression within <mo> elements whenever appropriate to mitigate such ambiguities.

If you have trouble working with invisible characters, for example if your IDE does not support showing such characters, you may use the following character references instead:

In the case of the invisible function application operator, it should be applied in-between the function identifier and its parameter list. If the parameters are surrounded by fences, the operator should be placed outside of the fences. Note that this also applies to probability functions, including when its parameter is the description of an event. If you're unsure whether an invisible function application operator should be applied, it helps to consider if the relevant elements are already linked due to another element or not.

Mathematical symbol or not?

There are a bunch of Greek letters and punctuation that look like their mathematical counterparts, but aren't. The latter should be used when applicable for proper rendering and parsing. When in doubt, search for the character in the Unicode code charts to see if it refers to such a look-a-like.

In particular, U+2212 – MINUS SIGN should generally be used instead of U+002D - HYPHEN-MINUS when used inside an <mo>, but never when setting attribute values.

Non-trivial use cases

Blank space

There are multiple ways to perform this, including:

Line breaks

Set an <mtable> with the displaystyle attribute to true as the direct child of the <math> element, with one row and cell per line.

2D elementary arithmetic

While it can be implemented with tables and lots of CSS trickery, 2D elementary arithmetic such as long division is not currently well-suited for MathML Core.

Truncated decimals with ellipsis

Use an <mn> containing the part of the real number prior to the truncation, followed by an <mo> containing an invisible plus, followed by an <mi> containing the ellipsis. Optionally, also put an <mo> containing the minus sign operator at the beginning of the expression if applicable. Place the entire expression inside an <mrow> if appropriate.

Repeating decimals

While it can be implemented with invisible operators and lots of CSS trickery, numbers with repeating decimals are better represented in MathML Core as fractions, mixed fractions or infinite sums.

If a mixed fraction is used, it should include an invisible plus operator.

Infinity

Infinity is not numeric, so an <mi> should be used.

Constants

It may be tempting to use an <mn> for constants like the Euler's number as they are real numbers, but an <mi> should actually be used instead unless the actual digits of such constants are represented.

Identifiers with static mathematical definitions

While writing a MathML Core expression, it is generally a good idea to follow the ISO 80000-2 standard to maximize international readability. Under normal circumstances, writing MathML Core expressions will generally apply said rules automatically based on heuristics, assuming the correct characters are used.

One common mistake however, and especially in English publications, is that mathematical constants and functions identifiers with a constant definition should NOT be rendered in italic. Therefore, when an <mi> element contains a single letter and represents such a constant or function, its mathvariant attribute should be set to normal. Note that this does not apply to physical constants or statistics, as they are technically variables derived from physical measurements. Also note that this does not apply to a probability function or distribution identified in the expression by a Latin capital or small P as its identifier.

Complex numbers

The real and imaginary parts of a complex number should be handled as separate elements, separated by a plus sign or minus sign operator, and grouped within <mrow>s if necessary. This should include an invisible times operator within the imaginary part of the number, which itself should be wrapped in an <mrow> due to operator precedence. A minus sign operator should also be included in the real part prior to its numeric size if applicable. Place the full expression inside an additional <mrow> if appropriate.

Once again, according to ISO 80000-2, the imaginary unit should use a normal i as its identifier, and because it is a mathematical constant, the mathvariant attribute of the corresponding <mi> should also be set to normal so that it is not rendered in italic.

Workarounds

Stretchy operators as direct children of <math> or <mtd>

Due to long-standing bug 236963 in Firefox, stretchy operators that are direct children of a <math> or <mtd> don't work properly in that browser. To work around this, an unnecessary <mrow> can be used until this issue is resolved.

Calculus in Leibniz notation or D-notation

Due to issue 256 in the MathML Core specifications, when using an <mo> containing a single Latin capital or small D to represent a derivative or integral, the incorrect spacing is applied around the operator. Without going into details as this is out of scope of this introduction, to work around this, such an element can have its lspace attribute set to 0.16666666666666666em its rspace attribute to 0 on it to apply the correct spacing until this issue is resolved.

Related content I wrote

Fireworks

The New Open Source Video Game Randomizer List Is Now Live

- Video Games, Programming

Time to update your bookmarks! After a few months of work behind the scenes, the new open source version of The BIG List of Video Game Randomizer is now live for your enjoyment, with dark mode support and a brand new UI for better readability! The new URL is: https://randomizers.debigare.com/ (The…

Open treasure chest with a question mark in it

The Future of the Video Game Randomizer List

- Video Games, Programming, Anecdotes

It's hard to believe that it's been almost 8 years since I first posted on the ROMhacking.net forums a list of video game randomizers that I found online, and that it would evolve into the massive project it has become today, with almost 900 entries currently being listed. It's always a strange…

Dice stacked in a triangle shape, with their face numbers matching their row position

I Designed the Perfect Gambling Game, But...

- Mathematics, Business, Game Design

Back in 2006-07-08, during the 13th Canadian Undergraduate Mathematics Conference at McGill University, I presented a gambling game I designed with the novel property of being both advantageous to players and the house, and that despite this proprety, that pretty much nobody in their right mind…

Stream of zeros and ones in space

Minifying JSON Text Beyond Whitespace

- Programming, Mathematics

JSON is a common data serialization format to transmit information over the Internet. However, as I mentioned in a previous article, it's far from optimal. Nevertheless, due to business requirements, producing data in this format may be necessary. I won't go into the details as to how one could…

Stream of concatenated JSON objects

Current Data Serialization Formats May Be a Waste of Money

- Programming, Business

Storing data. Transmitting data. Processing data. These fundamental topics of computer science are often overlooked nowadays thanks to the historical exponential growth of processing power, storage availability and bandwidth capabilities, along with a myriad of existing solutions to tackle them. So…

See all of my articles