Frédéric Wang Yet another non-exponentially growing weblog

About Me  Blog Archive

MathML in Chrome 109

2023/06/15: Most of this article was written in January 2023, but I only finished and published it in June. Hopefully, information is still up-to-date 😃

TL;DR

Igalia announced early this year that MathML is back to Chromium. This is an excellent news, for those like me who read and write mathematics on the web. Native support for such a universal human language sounds uncontroversial but it has taken a quarter century to get MathML implemented in all web engines… I invite you to listen to the corresponding episode of Igalia Chats where you can find some rationale about why it took so long. In this blog post, I’ll try to elaborate a bit about technical challenges we were able to overcome, thanks to the introduction of MathML Core. To be honest, things are still not perfect, but at least we can now rely on a clean foundation and continue to iterate improvements and fix bugs!

Timeline

As a reference, I’m providing below a list of important events (based on this timeline and this slide) for native MathML support in browsers:

A simple fraction

One of the first thing you can notice is that a significant portion of the work was done by volunteer contributors at the time when the set of requirements to ship a feature or integrate it in the specification was very small. Let’s consider some basic MathML formula to illustrate that:

<math style="font: 32pt STIX Two Math;">
  <mfrac>
    <mspace width="2em" height="1em" depth=".5em" style="background: red"/>
    <mspace width="2em" height=".5em" depth="1em" style="background: blue"/>
  </mfrac>
</math>

The <math> element is the root container for a new MathML formula. The <mfrac> element describes a fraction with two <mspace/> children corresponding respectively to its numerator and denominator. These <mspace/> elements are boxes of specified width, ascent and descent, as described by their width, height and depth attributes (using TEX terminology). Finally, the style attribute attaches inline style to MathML elements.

MathML 3 describes how to interpret the attributes of the <mspace> element. In general, it does not really define interaction with other web technologies and the behavior of the style attribute “is not specified”. However, browser implementers can safely assume it has the same syntax and semantic as HTML and that’s basically what MathML Core says. So we know the <math> element uses the font family STIX Two Math and font size of 32pt, while the <mspace> elements have red and blue background.

But how should we layout the <mfrac> element?

TEX-based layout

MathML 3 does not really say much more than the semantic “used for fractions” and the syntax <mfrac> numerator denominator </mfrac>. For the fraction bar, “the exact thickness of these is left up to the rendering agent”. MathML Core has a more detailed description involving vertical position and thickness of the fraction bar, minimal gaps between numerator/denominator and fraction bar as well as minimal shifts of the numerator/denominator’s baseline with respect to the baseline, horizontal centering of the numerator/denominator and more.

One of the essential part is that many of these parameters are taken from STIX Two Math’s Open Type MATH table such as fractionNumeratorShiftUp, fractionDenominatorGapMin etc and are generalizing the rules from the TEXBook. You may notice parameters like fractionNumeratorDisplayStyleShiftUp, fractionDenomDisplayStyleGapMin etc which are variants based on the math-style we will explain below.

In any case, as long as they follow the layout algorithm described in MathML Core, all browsers should now render the fraction example the same, right?

Exposing MathML magic

Assuming STIX Two Math is available or provided as a web font, Chrome and Firefox renders the previous example that way:

Screenshot of the example in Chromium 109

You can notice that the size of the numerator/denominator is different from what you get in Safari. Indeed, the web inspector shows that the <mspace> elements has a smaller font-size than the one of the <math> or <mfrac> elements. This magic is suggested by the remaining part of the description of MathML 3 we have ignored so far:

The mfrac element sets displaystyle to “false”, or if it was already false increments scriptlevel by 1, within numerator and denominator.

Let’s try to explain this a bit more. The displaystyle and scriptlevel properties are concepts from MathML 3 which are themselves generalizing TEX. Imagine many nested superscripts: the font size is scaled down each time you enter a superscript, and becomes smaller and smaller. Here, the scriptlevel corresponds to the nesting level and it affects the font size. Regarding displaystyle=false, this is typically used when you want to render the formula with more compact height e.g. for formulas rendered inline within a paragraph of text.

So the MathML 3 spec essentially says that the subformulas numerator/denominator should be rendered with compact height, and if we are already in such a mode we should even scale down the font size within these subformulas. The only problem is that this behavior is not specified at all by CSS!

In order to solve that, we introduced the math-style and math-depth CSS properties, explaining how they affect font-size in the cascade. That way the behavior can be completely handled by the CSS engines. Then MathML Core describes how displaystyle/scriptlevel attributes are treated as presentational hints together with appropriate rules in the User Agent stylesheet. At the end everything is well-specified and Safari’s behavior is a bug.

Integration with the web platform

The previous paragraphs described how we integrated TEX-based math layout inside the web platform. MathML 3 already started that by defined a SGML tree and HTML5 / MathML Core went further by defining the parsing rules, a WebIDL or integration with HTML and SVG.

The integration problem can also be seen on the other side: how do we interpret CSS features for math layout? For example what happens if one specifies a CSS width on the <mfrac> element? Or a padding? What would be the CSS layout if there are less or more children than just the numerator/denominator? What happen if float: left or position: absolute are specified on a child? Probably math authors don’t care too much but that’s still something that needs to be defined in the spec and implemented in a cross-compatible way.

Answering these questions were also useful for many reasons. Just to list a few examples off the top of my head:

  • In order to make things manageable, MathML Core focuses on a susbet of MathML 3 and some people are interested in writing polyfills for legacy or future features, which is something that can often be done by CSS.
  • Using a terminology that takes into account direction/writing-mode facilitates the implementation of right-to-left math and could allow vertical math in the future.
  • To avoid visual confusion between the fraction bar and another adjacent items (e.g. minus sign or another fraction’s bar), a default 1-pixel space is added around the element. This can be easily done by setting the padding in the User Agent stylesheet… as long as it’s supported!
  • Bypassing MathML layout in invalid subtrees (e.g. <mfrac> with three children) as was done in old implementations are making things harder for fuzzers and testcase reducers. Additionally these fuzzers often find issues happening with exotic CSS features, so better if the spec says how to handle them.

Web Platform tests

We’ve seen some examples on how to improve the MathML specification. This leads to the topic of Web Platform tests, which are very important to verify conformance with that specification and ensure browser interoperability. That’s a good tool and motivation for implementers and they may also prevent regressions since they are run regularly, at least each time a change is made in the browser repository.

However, MathML 3 was using manual tests where one has to visually compare the rendering of the 1675 testcases in a browser against a sample rendering and decide whether it passes or not. That’s a quite tedious and not very robust way of testing!

Fortunately, this has changed with MathML Core with around 3000 tests following the format of Web Platform tests! Trying to analyze that a bit, Chrome has an excellent pass rate except for things that need to be clarified in the spec. Firefox and Safari are also doing good job but failing on tests for new behavior or features that got clarified by MathML Core.

A complementary metrics for interoperability is MDN’s browser-compat-data. You can find these compatibility data at the bottom of MDN pages, for example for the MathML article. Again, a quick analysis confirms that browsers are quite interoperable for MathML Core, possibly mixed with other web technologies, but not for new CSS features (implemented in Chromium) or legacy MathML features (remaining in Firefox and Safari).

Accessibility

Abraham Nemeth who developed Braille code for mathematical notations, presented his view on math accessibility in the book Braille into the next millenium (2000):

The Principle of Meaning Versus Notation: In my view, it is the transcriber’s function to supply only notation, not meaning in an accessible form (speech or braille). It is the reader’s function to extract the meaning from the notation the transcriber supplies. Consider the common notation (x,y). That notation can mean many things: the ordered pair whose first component is x and second component is y ; the point in the cartesian coordinate with abscissa x and ordinate y; the open interval on the real line with left endpoint x and right endpoint y; or the greatest common divisor of x and y. The transcriber’s function, however, is only to convey this five-symbol expression to the reader. It is the reader’s function to extract whatever meaning his experience and the context of the text permit.

However, for people with different need, or for various uses cases, it is often important to provide more semantic. This is something various members from the MathML WG have worked on and many discussions are currently happening.

In any case, for native MathML implementation in browsers we are limited to what was called “presentation MathML” in legacy specifications, which gives a very small amount of information: an <mfrac> can be fraction, binomial coefficient etc ; an <msup> can be used to denote a power, a derivative, an index etc ; an <mtable> can be used for matrices, to perform table layout etc

As explained above, some effort was done to implement native accessibility support for MathML in WebKit/Gecko for various assistive technologies in Linux, macOS or Windows. For the present project, we didn’t try to do more than what currently exists. We only documented existing support in the MathML AAM specification and implemented it in Chromium. This is the bare minimum we can do to ensure the reader can follow Nemeth’s approach.

Conclusion

As the main person who has led this effort, this is great personal achievement and I’d like to thank all the people who supported it, including my colleagues at Igalia, members of the MathML community, standardization groups, browser developers, web developers, sponsors and contributors to the Open Collective. Finally we made it! 🎉