You’re reading Ry’s MathML Tutorial

Advanced Formatting

By now, we’ve covered pretty much all of the MathML tags for marking up equations. This module shows you how to format these elements and integrate them with the surrounding HTML content. We’ll talk about colors, font sizes, inline expressions, whitespace editing, and phantom elements.

Browser support for some of these formatting options is spotty, so you are strongly encouraged to use the MathJax template discussed at the beginning of this tutorial.

Colors

While they’re not exactly “advanced” formatting options, this is a fitting place to introduce the mathcolor and mathbackground attributes. These let you set the text color and background color of MathML elements, which is useful for highlighting important aspects of an equation. Both attributes take a hexadecimal color as a value:

<math xmlns="http://www.w3.org/1998/Math/MathML" display='block'>
  <msup>
    <mi>e</mi>
    <mrow mathcolor='#cc0000'>
      <mn>2</mn>
      <mi>x</mi>
      <mo>+</mo>
      <mn>1</mn>
    </mrow>
  </msup>
</math>

This tells the renderer to draw the entire exponent in red:

These two attributes can be applied to any Presentation Markup—they aren’t limited to the token elements like mathvariant is. This makes it possible to cascade colors to an element’s children, as we saw with <mrow> above.

Font Sizes

The mathsize works in a similar fashion, except it takes a measurement specified in em, px, pt, etc. For example, we can increase the size of the e just a little bit using the following snippet.

<math xmlns="http://www.w3.org/1998/Math/MathML" display='block'>
  <msup>
    <mi mathsize='1.2em'>e</mi>
    <mrow mathcolor='#00cc00'>
      <mn>2</mn>
      <mi>x</mi>
      <mo>+</mo>
      <mn>1</mn>
    </mrow>
  </msup>
</math>

This makes the base 1.2 times the current font height, resulting in the rendering shown below.

Font sizes can only be applies to token elements (<mi>, <mn>, and <mo>), which means you cannot apply it to an <mrow> like mathcolor. Instead, you need to use a style group.

Style Groups

The <mstyle> element represents a change in the default style for all child elements. If we want an entire group of elements to use a smaller font, you simply wrap them in an <mstyle> element and set the mathsize attribute on that, like so:

<math xmlns="http://www.w3.org/1998/Math/MathML" display='block'>
  <msup>
    <mi>e</mi>
    <mstyle mathcolor='#0000cc' mathsize='.7em'>
      <mn>2</mn>
      <mi>x</mi>
      <mo>+</mo>
      <mn>1</mn>
    </mstyle>
  </msup>
</math>

This tells the contained <mn>, <mi>, and <mo> elements to change their size to .7 times the current font height. Also notice that <mstyle> creates an inferred row, so we can safely omit the <mrow> tag.

You can override an <mstyle>’s default value by explicitly setting the same attribute on the target child element.

Inline Expressions

For the entirety of this tutorial, we’ve been rendering expressions as block formulas, but MathML also provides inline formulas. Whereas block formulas are rendered in their own formatting block, inline expressions appear alongside prose. For this reason, a more compact form is typically chosen for inline expressions:

Block summation with over/underscripts vs inline summation with super/subscripts

As mentioned at the beginning of this tutorial, the rendering mode is determined by the display attribute of the top-level <math> element. To change a block expression into an inline one, set display to inline, then include the expression inside of the surrounding text:

<p>The series
<math xmlns="http://www.w3.org/1998/Math/MathML" display='inline'>
  <munderover>
    <mo>&sum;</mo>
    <mrow>
      <mi>n</mi>
      <mo>=</mo>
      <mn>1</mn>
    </mrow>
    <mi>&infin;</mi>
  </munderover>
  <mfrac>
    <mn>1</mn>
    <mi>n</mi>
  </mfrac>
</math>
is divergent.</p>

To fit the expression onto a single line, the renderer should display the over/underscripts as super/subscripts and shrink the summation symbol and fraction. The result is a high-quality layout with the expression seamlessly integrating into the surrounding text.

The series ∑ 1/n from n=1 to infinity is divergent.

Different expressions will require different changes (e.g., shorter integral signs), and some simply can’t be displayed inline. Most of these decisions are left to the rendering engine, but there is one common exception, discussed below.

Movable Limits

Next, let’s try to create an inline limit using the above technique. Our goal is to mark up the following:

lim 1/x as x approaches infinity with bounds rendered as subscript

A logical first attempt might look something like:

<p><math xmlns="http://www.w3.org/1998/Math/MathML" display='inline'>
  <munder>
    <mo>lim</mo>
    <mrow>
      <mi>x</mi>
      <mo>&rarr;</mo>
      <mn>0</mn>
    </mrow>
  </munder>
  <mo>&ApplyFunction;</mo>
  <mfrac>
    <mn>1</mn>
    <mi>x</mi>
  </mfrac>
</math>
equals infinity.</p>

Unfortunately, this won’t change the underscript to a subscript. A display='inline' attribute is just half the story for inline over/underscripts. We also need to define the movablelimits attribute on the base of the <munder> tag. If it’s set to true, a MathML renderer is allowed to display limits as super/subscripts, but if it’s false, they must be displayed as true over/underscripts.

So, let’s change the <mo>lim</mo> element to the following:

    <mo movablelimits='true'>lim</mo>

This should give us the desired result. You’re probably wondering why we didn’t have to do this for the summation in the previous step. Certain characters, including &sum;, implicitly set movablelimits to true. But, this varies among rendering engines so it’s safer to define it explicitly.

The point to remember is that an inline limit requires two things:

  1. display='inline' on the top-level <math> element
  2. movablelimits='true' on the base of <munder>/<munderover>

Also note that movablelimits can only be defined on an <mo> element, so don’t try to use an identifier or a number as a base.

Combining Text and MathML

In MathML, there are three standard ways to combine mathematical expressions with text:

The previous two examples demonstrated the first technique, which is the preferred way to mix text and formulas when writing articles or books. But, if the text represents a mathematical entity, it’s better to wrap it in <mo> or <mi> tags. We saw this in the Over/Underscripts section when we placed an ellipsis in an <mi> tag and in Piecewise Functions when we marked up the if statement as an operator.

MathML’s <mtext> element opens up the third possibility of embedding text directly into a formula. For example, consider the following expression.

Theorem 1: if x>1 then x^2>x

Theorem 1 can’t be marked up as an operator or an identifier. This leaves either plain HTML and an inline MathML expression, or an <mtext> element. Examples of both are shown below.

<!-- Plain HTML with inline expression -->
<p>Theorem 1:
<math xmlns="http://www.w3.org/1998/Math/MathML" display='inline'>
  <mo>if</mo>
  <mi>x</mi>
  <mo>&gt;</mo>
  <mn>1</mn>
  <mo>then</mo>
  <msup>
    <mi>x</mi>
    <mn>2</mn>
  </msup>
  <mo>&gt;</mo>
  <mi>x</mi>
</math></p>

This inline version is better if you’re using the expression within a paragraph. However, if you want to display the expression in its own formatting block, you’ll want to use an <mtext> element, like so:

<!-- Embedded text with block expression -->
<math xmlns='http://www.w3.org/1998/Math/MathML' display='block'>
  <mtext>Theorem 1:</mtext>
  <mo>if</mo>
  <mi>x</mi>
  <mo>&gt;</mo>
  <mn>1</mn>
  <mo>then</mo>
  <msup>
    <mi>x</mi>
    <mn>2</mn>
  </msup>
  <mo>&gt;</mo>
  <mi>x</mi>
</math>

Either option will work, but it’s important to remember that <mtext> is meant to define commentary or expository text—not meaningful mathematical elements. Do not use it to mark up text that replaces a variable or operator.

Custom Spaces

If you try to put a space inside of an <mtext> element, you’ll quickly realize that MathML strips surrounding whitespace from elements. To insert a space into an expression, you need to use the empty <mspace/> element and its width attribute. For example, if you wanted to add a little bit of space between the words from the previous step, you could use the following.

<math xmlns='http://www.w3.org/1998/Math/MathML' display='block'>
  <mtext>Theorem 1:</mtext>
  <mspace width='.1em' />
  <mo>if</mo>
  <mspace width='.1em' />
  <mi>x</mi>
  <mo>&gt;</mo>
  <mn>1</mn>
  <mo>then</mo>
  <mspace width='.1em' />
  <msup>
    <mi>x</mi>
    <mn>2</mn>
  </msup>
  <mo>&gt;</mo>
  <mi>x</mi>
</math>

This can also be accomplished by adding an lspace or rspace attribute to an <mo> element, but <mspace/> is a little bit more flexible since it can be defined anywhere in an equation. The result is shown below.

Theorem 1: if x>1 then x^2>x with more spacing between words

One em is equal to the current font height, so this is a relatively robust method of adding spaces (the <mspace/>’s will scale with the font size). However, this kind of “tweaking” often proves more trouble than it’s worth: due to the inconsistencies in rendering engines and the medium-independent nature of HTML, your “perfect” layout won’t look nearly as good in other applications. Unless you know exactly how your audience will be viewing your MathML, it’s usually best to stick with the default layout.

It’s important to understand that spaces should never be used to convey mathematical meaning—your formula should read the same even if all of the <mspace/>’s were removed. For this reason, most rendering engines use a default width of 0, so you’ll pretty much always have to define it on your own.

Custom Linebreaks

In addition to horizontal space, the <mspace/> element also lets you declare line breaks with the aptly named linebreak attribute. This is useful, for example, to manually break a long expression onto multiple lines:

Long expression broken manually

To create such a linebreak, all you need is the following.

<mspace linebreak='newline' />

If you would rather provide hints to the rendering engine and let it break lines on its own, you can use the following values for the linebreak attribute:

Value Description
nobreak Forbid a line break at this location.
badbreak Try to prevent a line break at this location.
goodbreak Suggest a line break at this location.

Since linebreaks often occur at operators, MathML lets you use all of these attributes on the <mo> element, too. But, since you’re now breaking on a visible symbol, you’ll need the linebreakstyle attribute to specify whether the newline should be before the operator, after the operator, or if the operator should be duplicated and appear on both lines. Valid values are (respectively): before, after, and duplicate.

So, instead of using an <mspace/> as in the previous example, you could specify it directly on the last operator in the line:

<mo linebreak='newline' linebreakstyle='after'>+</mo>

Custom Indentation

The MathML specification gives you control over how subsequent lines are indented after a linebreak. The indentalign attribute controls the alignment of the line, and indentshift controls the size of the indent. Both of these can be defined on <mo>, <mspace/>, and the top-level <math> element. They can be used to align multi-step evaluations of an expression, like so:

Two-line equation lined up at the equal sign

You’re supposed to be doing this kind of alignment with the indenttarget attribute, but this functionality is poorly implemented across MathML rendering engines. Instead we’re stuck with manual indents:

<math xmlns="http://www.w3.org/1998/Math/MathML"
      display='block'
      indentalign='left'>
  <mrow>
    <msup><mi>x</mi><mn>2</mn></msup>
    <mo>-</mo>
    <mn>9</mn>
  </mrow>
  <mo>=</mo>
  <mrow>
    <msup><mi>x</mi><mn>2</mn></msup>
    <mo>-</mo>
    <msup><mn>3</mn><mn>2</mn></msup>
  </mrow>
  <mo linebreak='newline'
      linebreakstyle='before'
      indentshift='2.6em'>=</mo>
  <mrow>
    <mfenced separators=''>
      <mi>x</mi><mo>-</mo><mn>3</mn>
    </mfenced>
    <mo>&InvisibleTimes;</mo>
    <mfenced separators=''>
      <mi>x</mi><mo>+</mo><mn>3</mn>
    </mfenced>
  </mrow>
</math>

First, this snippet changed the alignment of the entire <math> element to left, since it’s a much easier way to align multiple lines. Then, we specified a line break at the second = sign and indented it to align with the first = sign. 2.6em is the approximate width of the left-hand-side of the equation, determined through trial and error.

Yes, this is a tedious way to align equations, but at least it uses em units so that the alignment will be unaffected by changes in font sizes. The next section takes a look at a better way to align expressions.

Hiding Sub-Expressions

The <mphantom> element makes the contained mathematical expression disappear, but the rest of the expression renders as if it were still there. This is a much more robust way to align equations than manual indentation. For example, the factorization from the previous step can be aligned with the following:

<math xmlns="http://www.w3.org/1998/Math/MathML"
      display='block'
      indentalign='left'>
  <mrow>
    <msup><mi>x</mi><mn>2</mn></msup>
    <mo>-</mo>
    <mn>9</mn>
  </mrow>
  <mo>=</mo>
  <mrow>
    <msup><mi>x</mi><mn>2</mn></msup>
    <mo>-</mo>
    <msup><mn>3</mn><mn>2</mn></msup>
  </mrow>
  <mspace linebreak='newline' />

  <mphantom>
    <msup>
      <mi>x</mi><mn>2</mn>
    </msup>
    <mo>-</mo>
    <mn>9</mn>
  </mphantom>
  <mo>=</mo>
  <mrow>
    <mfenced separators=''>
      <mi>x</mi><mo>-</mo><mn>3</mn>
    </mfenced>
    <mo>&InvisibleTimes;</mo>
    <mfenced separators=''>
      <mi>x</mi><mo>+</mo><mn>3</mn>
    </mfenced>
  </mrow>
</math>

In the second line, the left-hand-side of the equation still exists in the MathML, which ensures that the equal sign lines up with the first line. Then, we simply hide it by wrapping it in <mphantom> tags. Since we’re essentially faking the equal-sign alignment, we also had to use an <mspace/> to create the line break instead of a adding it to an <mo>.

From a pedagogical perspective, <mphantom> presents an intuitive way to mark up fill-in-the-blank questions. It lets you create the full expression, and then turn some of the elements into blanks:

<math xmlns="http://www.w3.org/1998/Math/MathML"
      display='block'
      indentalign='left'>
  <mrow>
    <msup><mi>x</mi><mn>2</mn></msup>
    <mo>-</mo>
    <mn>9</mn>
  </mrow>
  <mo>=</mo>
  <mrow>
    <msup>
      <mi>x</mi>
      <mn>2</mn>
    </msup>
    <mo>-</mo>
    <msup>
      <mrow>
        <mphantom style='border: 2px solid #000; padding: 5px;'>
          <mn>3</mn>
        </mphantom>
      </mrow>
      <mn>2</mn>
    </msup>
  </mrow>
</math>

With the help of some inline CSS, <mphantom> turned the second term in the right-hand-side into an empty box:

As you might imagine, the fact that MathML can be seamlessly combined with CSS opens up a vast array of possibilities for formatting equations. But, the creative side of styling equations and worksheets is a bit outside the scope of this tutorial, so we’ll leave that for you to explore on your own.

Summary

In this module, we wrapped up our discussion of MathML by looking at several advanced formatting features. We learned how to change the color and size of expressions, create inline elements with display='inline' and movablelimits='true', and customize whitespace using <mspace/>.

Remember that different rendering engines have different default spacing behavior, so make sure you know your target output format before you start tweaking equations in search of the perfect layout.

And that’s everything you need to know about MathML for typical daily usage. You should now have all the skills you need to embed complex equations directly into your web pages. Be sure to check out the final module of this tutorial for a handy mathematical entity reference, too.

Of course, if you have any questions, comments, or suggestions, please don’t hesitate to contact us.

Mailing List

Sign up for my low-volume mailing list to find out when new content is released. Next up is a comprehensive Swift tutorial planned for late January.

You’ll only receive emails when new tutorials are released, and your contact information will never be shared with third parties. Click here to unsubscribe.