Configuring and Loading MathJax

The configuration, loading, and startup processes for MathJax version 3 are different from those of version 2 in a number of ways. Where version 2 had several different methods for configuring MathJax, version 3 streamlines the process and has only one, as described below. In version 2, you always loaded MathJax.js, and added a config=... parameter to provide a combined configuration file, but in version 3 you load one of several different files, depending on your needs (so you can avoid multiple file transfers, and also use MathJax synchronously, which was not possible in version 2).

If you use one of the combined component files in version 3, like mml-chtml, you may not need to do any configuration at all.


Configuring MathJax

To configure MathJax, you use a global object named MathJax that contains configuration data for the various components of MathJax. For example, to configure the TeX input component to use single dollar signs as in-line math delimiters (in addition to the usual \(...\) delimiters) and the SVG output component to use a global font cache for all expressions on the page, you would use

MathJax = {
  tex: {
    inlineMath: [['$', '$'], ['\\(', '\\)']]
  },
  svg: {
    fontCache: 'global'
  }
};

The sections below describe the different places you could put such a configuration. For information on the options that you can set for each of the components, see the Configuring MathJax pages.

Configuration Using an In-Line Script

The easiest way to configure MathJax is to place the MathJax object in a <script> tag just before the script that loads MathJax itself. For example:

<script>
MathJax = {
  tex: {
    inlineMath: [['$', '$'], ['\\(', '\\)']]
  },
  svg: {
    fontCache: 'global'
  }
};
</script>
<script type="text/javascript" id="MathJax-script" async
  src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js">
</script>

This will configure the TeX input component to use single dollar signs as in-line math delimiters, and the SVG output component to use a global font cache (rather than a separate cache for each expression on the page), and then loads the latest version of the tex-svg component file from the jsdelivr CDN. This will typeset any TeX mathematics on the page, producing SVG versions of the expressions.

Using a Local File for Configuration

If you are using the same MathJax configuration over multiple pages, you may find it convenient to store your configuration in a separate JavaScript file that you load into the page. For example, you could create a file called mathjax-config.js that contains

window.MathJax = {
  tex: {
    inlineMath: [['$', '$'], ['\\(', '\\)']]
  },
  svg: {
    fontCache: 'global'
  }
};

and then use

<script src="mathjax-config.js" defer></script>
<script type="text/javascript" id="MathJax-script" defer
  src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js">
</script>

to first load your configuration file, and then load the tex-svg component from the jsdelivr CDN.

Note that here we use the defer attribute on both scripts so that they will execute in order, but still not block the rest of the page while the files are being downloaded to the browser. If the async attribute were used, there is no guarantee that the configuration would run first, and so you could get instances where MathJax doesn’t get properly configured, and they would seem to occur randomly.

Configuring and Loading in One Script

It is possible to have the MathJax configuration file also load MathJax as well, which would be another way to handle the problem of synchronizing the two scripts described above. For example, you could make the file load-mathjax.js containing

window.MathJax = {
  tex: {
    inlineMath: [['$', '$'], ['\\(', '\\)']]
  },
  svg: {
    fontCache: 'global'
  }
};

(function () {
  var script = document.createElement('script');
  script.src = 'https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js';
  script.async = true;
  document.head.appendChild(script);
})();

and then simply link to that file via

<script src="load-mathjax.js" async></script>

This script can be async because it doesn’t have to synchronize with any other script. This will allow it to run as soon as it loads (since it is small, there is little cost to that), meaning the script to load MathJax itself will be inserted as soon as possible, so that MathJax can begin downloading as early as possible. (If this script were loaded with defer, it would not run until the page was ready, so the script to load MathJax would not be inserted until then, and you would have to wait for MathJax to be downloaded before it could run.)

Converting Your v2 Configuration to v3

Because the version 3 configuration options are somewhat different from their version 2 counterparts, we provide an automated configuration conversion tool to help you move from version 2 to version 3. Simply paste your current MathJax.Hub.Config() call into the converter, press Convert and you should get the equivalent version 3 configuration, and comments about any options that could not be translated to version 3 (some options are not yet implements, others no longer make sense in version 3). See the instructions on the linked page for more details.


Loading MathJax

Once you have configured MathJax, you then load the MathJax component file that you want to use. Most often, this will mean you load a combined component that loads everything you need to run MathJax with a particular input and output format. For example, the tex-svg component would allow you to process TeX input and produce SVG output. To do so, use a script like the following

<script type="text/javascript" id="MathJax-script" async
  src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js">
</script>

to get the latest (3.x.x) version of the tex-svg component in ES5 format (the only one currently available) from the jsdelivr CDN. This takes advantage of the feature of jsdeliver that allows you to get the latest version using the mathjax@3 notation. For a specific version, you would use

<script type="text/javascript" id="MathJax-script" async
  src="https://cdn.jsdelivr.net/npm/mathjax@3.0.0/es5/tex-svg.js">
</script>

to always get the 3.0.0 version of the tex-svg component.

Other CDNs have slightly different formats for how to specify the version number. For example, cdnjs uses the following:

<script type="text/javascript" id="MathJax-script" async
  src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/3.0.0/es5/tex-svg.js">
</script>

Some CDNs don’t provide a means of getting the latest version automatically. For these, MathJax provides a latest.js file that will do that for you. For example, cdnjs doesn’t have a mechanism for getting the latest 3.x.x version automatically. If you want to do that using cdnjs, then use

<script type="text/javascript" id="MathJax-script" async
  src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/3.0.0/es5/latest?tex-svg.js">
</script>

to obtain the latest (3.x.x) version of the tex-svg component.

See The MathJax Components for a list of the various components you can choose and descriptions of their contents. See the list of CDNs for the URLs for a number of CDNs that serve MathJax.

Note that the script that loads the MathJax component file should follow the script that configures MathJax (otherwise MathJax will not know what configuration you need). If you use one of the combined component files in version 3, you may not need to do any configuration at all.

Loading Components Individually

If none of the combined component files suits your needs, you can specify the individual components you want by setting the load array in the loader section of your MathJax configuration and loading the startup component.

For example

<script>
MathJax = {
  loader: {
    load: ['input/tex-base', 'output/svg', 'ui/menu', '[tex]/require']
  },
  tex: {
    packages: ['base', 'require']
  }
};
</script>
<script type="text/javascript" id="MathJax-script" async
  src="https://cdn.jsdelivr.net/npm/mathjax@3.0.0/es5/startup.js">
</script>

would cause the base TeX input, the SVG output, the contextual menu code, and the TeX \require macro extension components to be loaded (and would tell TeX to use the require extension in addition to the base TeX macros). In this way, you can load exactly the components you want. Note, however, that each component will be loaded as a separate file, so it is better to use a combined component file if possible.

Loading Additional Components

You can use the load array described in the previous section to load additional components even if you are using one of the combined components. For example

<script>
MathJax = {
  loader: {
    load: ['[tex]/colorv2']
  },
  tex: {
    packages: {'[+]': 'colorv2'},
    autoload: {color: []}
  }
};
</script>
<script type="text/javascript" id="MathJax-script" async
  src="https://cdn.jsdelivr.net/npm/mathjax@3.0.0/es5/tex-chtml.js">
</script>

would load the version-2-compatible \color macro, inform TeX to add that to the packages that it already has loaded, and not autoload the default version 3 color (the LaTeX-compatible one). This is done on top of the tex-chtml combined configuration file, so the TeX input and CommonHTML output formats are already included (as are the contextual menu, and several TeX packages; see The MathJax Components for details).

Performing Actions During Startup

MathJax allows you several ways to hook into the MathJax startup process so that you can do additional configuration, perform actions after the initial typesetting, and so on. Because MathJax version 3 uses promises for its synchronization, they are what MathJax provides in order for you to hook into the startup process. There are two main hooks that you can set in the startup block of your configuration: the ready() function and the pageReady() function.

The ready() function is what MathJax calls when all the components of MathJax have been loaded. It builds the internal structures needed by MathJax, creates functions in the MathJax object to make typesetting and format conversion easy for you, performs the initial typesetting call, and sets up a promise for when that is complete. You can override the ready() function with one of your own to override the startup process completely, or to perform actions before or after the usual initialization. For example, you could do additional setup before MathJax created the objects it needs, or you could hook into the typesetting promise to synchronize other actions with the completion of the initial typesetting. Examples of these are given below.

The pageReady() function is performed when MathJax is ready (all its components are loaded, and the internal objects have been created), and the page itself is ready (i.e., it is OK to typeset the page). The default is for pageReady() to perform the initial typesetting of the page, but you can override that to perform other actions instead, such as delaying the initial typesetting while other content is loaded dynamically, for example. The ready() function sets up the call to pageReady() as part of its default action.

The return value of pageReady() is a promise that is resolved when the initial typesetting is finished (it is the return value of the initial MathJax.typesetPromise() call). If you override the pageReady() method, your function should return a promise as well. If your function calls MathJax.startup.defaultPageReady(), then you should return the promise that it returns (or a promise obtained from its then() or catch() methods). The MathJax.startup.promise will resolve when the promise you return is resolved; if you don’t return a promise, MathJax.startup.promise will resolve immediately, which may mean that it resolves too early.

Using these two functions separately or in combination gives you full control over the actions that MathJax takes when it starts up, and allows you to customize MathJax’s startup process to suit your needs. Several examples are given below for common situations.

Performing Actions During Initialization

If you want to perform actions after MathJax has loaded all the needed components, you can set the ready() function to a function that does the needed actions, and then calls MathJax.startup.defaultReady() to perform the usual startup process.

Actions coming before the MathJax.startup.defaultReady() call are run before any initialization has been done. In particular, this is before any input or output jax are created, so this is where customization of the MathJax object definitions could be performed. For example, you could modify the configuration blocks at this point, or you could create subclasses of the MathJax objects that override some of their methods to produce custom behavior, and then register those subclasses with MathJax so they will be used in place of the originals.

Actions coming after the MathJax.startup.defaultReady() call are run after initialization is complete. In particular, all the internal objects used by MathJax (e.g., the input and output jax, the math document, the DOM adaptor, etc) will have been created, and the typesetting and conversion methods will have been created in the MathJax object. Also the MathJax.startup.promise value will hold a promise that is resolved when the initial typesetting is complete, but note that the typesetting has not yet been performed at this point.

window.MathJax = {
  startup: {
    ready: () => {
      console.log('MathJax is loaded, but not yet initialized');
      MathJax.startup.defaultReady();
      console.log('MathJax is initialized, and the initial typeset is queued');
    }
  }
};

The next section shows how to use the MathJax.startup.promise to synchronize with the initial typesetting action.

Performing Actions After Typesetting

Often, you may need to wait for MathJax to finish typesetting the page before you perform some action. To accomplish this, you can override the ready() function, having it perform the MathJax.startup.defaultReady() action, and then use the MathJax.startup.promise to queue your actions; these will be performed after the initial typesetting is complete.

window.MathJax = {
  startup: {
    ready: () => {
      MathJax.startup.defaultReady();
      MathJax.startup.promise.then(() => {
        console.log('MathJax initial typesetting complete');
      });
    }
  }
};

As an alternative, you can override the pageReady() function, and use the promise returned from the MathJax.startup.defaultPageReady() function:

window.MathJax = {
  startup: {
    pageReady: () => {
      return MathJax.startup.defaultPageReady().then(() => {
        console.log('MathJax initial typesetting complete');
      });
    }
  }
};

Be sure that you return the promise that you obtain from then() method, otherwise MathJax.startup.promise will resolve before the initial typesetting (and your code) has been performed.


Configuring MathJax After it is Loaded

The global variable MathJax is used to store the configuration for MathJax. Once MathJax is loaded, however, MathJax changes the MathJax variable to contain the various methods needed to control MathJax. The initial configuration that you provided is moved to the MathJax.config property so that its contents doesn’t conflict with the new values provides in MathJax. This occurs when the MathJax component you have requested is loaded (and before the ready() function is called).

Once MathJax has created the objects that it needs (like the input and output jax), changes to the configuration may not have any effect, as the configuration values were used during the creation of the objects, and that is already complete. Most objects make a copy of their configuration from your original MathJax object, so changing the values in MathJax.config after the objects are created will not change their configurations. (You can change MathJax.config values for objects that haven’t been created yet, but not for ones that have.)

For some objects, like input and output jax, document handlers, and math documents, the local copies of the configuration settings are stored in the options property of the object, and you may be able to set the value there. For example, MathJax.startup.output.options.scale is the scaling value for the output, and you can set that at any time to affect any subsequent typeset calls.

Note that some options are moved to sub-objects when the main object is created. For example, with the TeX input jax, the inlineMath and similar options are used to create a FindTeX object that is stored at MathJax.startup.input[0].findTeX; but in this case, the FindTeX object uses the configuration once when it is created, so changing MathJax.startup.input[0].findTeX.options will not affect it. (There is a getPatterns() method if the FindTeX object that could be used to refresh the object if the options are changed, however.)

If you need to change the configuration for an object whose options can’t be changed once it is created, then you will need to create a new version of that object after you change the configuration. For example, if you change MathJax.config.tex.inlineMath after MathJax has started up, that will not affect the TeX input jax, as described above. In this case, you can call MathJax.startup.getComponents() to ask MathJax to recreate all the internal objects (like MathJax.startup.input). This will cause them to be created using the new configuration options. Note, however, that MathJax will no longer know about any mathematics that has already been typeset, as that data was stored in the objects that have been discarded when the new ones are created.