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:
- 1993-1995: Early HTML specifications contained a
<MATH>
tag, which was experimented in Dave Raggett’s Arena browser. - 1998-2003: Initial specifications of MathML were published. Volunteer contributor Roger Sidje added support in Gecko for XHTML documents and that was released in Mozilla 1.0.
- 2006-2013:
- MathML was integrated in HTML5. George Chavchanidze created a CSS-based implementation and shipped it in Opera. Support was implemented in all Open Source browsers thanks to the effort of volunteer contributors (including Roger Sidje, François Sausset, Alex Miłowski, Dave Barton and myself). However, MathML was removed from Chrome shortly after.
- Apple engineers, notably Chris Fleizach and James Craig, implemented NSAccessibility support for WebKit and VoiceOver.
- 2014-2016:
- I published an implementation note with extra rendering rules based on Donald Knuth’s TEXBook and Microsoft’s OpenType MATH table. I implemented these rules in Gecko and WebKit via a crowdfunding project.
- During a few codecamps and hackfests, Joanmarie Diggs (Igalia), Alexander Surkov (at that time at Mozilla) and I (who just joined the AcceSciTech project) worked on ATK and NSAccessibility support for Gecko, WebKit and Orca.
- Jamie Teh and Neil Soiffer added MathML accessibility support for Gecko and Chromium by exposing the raw source code via a dedicated MSAA API.
- Igalia performed a big refactoring of WebKit’s implementation. Initially done by Alejandro García in 2015, I took over the work when I joined the company the following year.
- 2019-2023:
- Igalia launched the “MathML in Chromium” project with the support of various sponsors. Rob Buis and I worked on a brand new implementation in Chromium. Brian Kardell also joined Igalia at the beginning of the project and has been instrumental in communication, advocacy and standardization efforts.
- A new MathML Core specification became the reference for browser implementations and was shipped in Chromium 109.
- Alexander Surkov joined Igalia and helped with the MathML AAM specification, which we used to implement ATK and NSAccessibility support in Chromium.
- I’ve regularly presented our results in conferences. For completeness, here are the talks I gave:
- November 2022: Shipping MathML in Chrome 109 at BlinkOn 17 - video.
- June 2022: Shipping MathML in Chrome at the Web Engines Hackfest.
- May 2022: Remainder estimate for MathML integration - video.
- November 2021: MathML, onde estamos? - video.
- November 2019: MathML Core at BlinkOn 11.
- October 2019: MathML in Browsers at the Web Engines Hackfest - video.
- April 2019: MathML in LayoutNG at BlinkOn 10.
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:
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! 🎉