SVGMath overview
Explanation
SVGMath is a way to produce good looking math on the Web, without using the javascript-based approaches of MathJax or KaTeX. It's an SVG-based approach to fast loading of beautiful math on the Web.
See the SVGMath demo page .
SVGMath is a proof-of-concept attempt at solving the following issues when displaying math on the Web:
- MathJax and KaTeX are javascript-based libraries that convert LaTeX (or MathML) to attractive mathematics for easy reading
- Being javascript based, it takes time for the javascript to load, and takes even more time to process and display the math. While developers of both libraries have put a lot of effort into making things as fast as possible, users are impatient when pages take a long time to load and will tend to abandon them. There's a search engine penalty for slow sites as well.
- Most sites already have a large volume of "javascript soup" (including libraries like JSNode, jQuery, etc, and/or advertising, social network widgets, and so on). All of this soup competes with each other as the page loads, slowing everything down.
- Both MathJax and KaTeX libraries produce a huge number of HTML elements (
<span>
s, mostly) that are necessary to display the math properly. Such DOM creation and manipulation is a big reason why loading and processing take so long. Page analysis tools like Lighthouse complain bitterly about page load blocking and the large number of DOM elements on such pages. - Both libraries provide MathML output for accessibility reasons (blind people can make use of MathML for exploring within math and copying portions). This adds to the large number of DOM elements created.
So this page is an attempt to address some of the above items.
- There is no javascript used at all for equation processing on page load (except some sizing tweaks for narrow screens)
- We're embedding SVGs only, and doing it using "lazy loading" (so the browser only loads the SVGs as the user scrolls down to them).
- In 2 out of the 3 output versions, the SVGs use
<text>
tags instead of<path>
s for all numbers and variables. This makes each SVG considerably smaller, since we call the fonts once on page load (and don't draw a picture of each character, like in<path>
s). - SVGMath includes screen reading facilities (
aria-label
s) but not MathML by default, since the majority of users don't require such things. (Try the demo page with a screen reader.) - Equation tags (numbering) successfully appear if
\label{...}
is present in the equation, and links to those numbered equations also work.
How it's done
- The page is processed on the server (by PHP) so it's complete before it appears in the user's browser. It works somewhat similarly to a Wordpress plugin, where the LaTeX equations on the page are replaced by math.
- In the development phase for a page, all the
\begin{equation} ... \end{equation}
,$$... $$
,$ ... $
, etc are replaced with a call to MathJax-SVG, and each equation in SVG form is written to the server. - Once the SVGs exist on the server, they are lazy-load added to the page using AJAX (or in the image case, actually lazy loaded). The SVGs are cached and don't need to be created again.
- For the demo, I created 3 versions:
- Inline SVG, using
<text>
tags and with fonts called (once) in the HTML<tag>
tag, loaded using my own lazy loader - SVGs using
<text>
tags this time embedded in<object>
tags, which require a call to the fonts in each equation, once again loaded using my own lazy loader - SVGs using
<path>
tags this time called in<img>
tags, and loaded usingloading="lazy"
- Inline SVG, using
- Any equation tags are extracted and added as a <span> on the far right of the equation.
- Any tag links are kept track of by arrays and the
\eqref
are converted to links and point to the correct equation. - Of course, the whole thing is phone-friendly
Accessibility
Rather than load accessibility elements for everyone, SVGMath includes enough information for a screen reader to produce spoken math, derived from MathJax's screen reader text ooutput.
Try the page using a screen reader to hear the result.
(If equation exploration and copying facilities are required, it makes more sense to use MathJax or KaTeX.)
Comparison Stats
There are different versions of SVGMath here for comparison. The stats given here are roughly what I saw in my environment. There are many variables and your mileage will differ.
All of the SVGMath examples mentioned here make use of lazy loading techniques, so that initial page load is as fast as possible. (MathJax has a lazy load option, which I am not using for these comparison tables.)
Cells with green background are the best, red is last.
(1) Inline SVGs using <text> tags
This is the best version for performance. The resource use is low and the number of DOM elements is roughly 1/3 of those produced by MathJax or KaTeX.
We're using <text> tags for numbers and variables, rather than <path>s (which is what MathJax uses in its SVG version.) We're also using a simple <span> element (not a whole SVG) for the very simple (one-character) math items (like "x") where it's overkill to use an antire SVG.
One downside of this technique is it's not so good for SEO (search engine optimisation) as the SVGs are embedded, not existing as a separate file, so they never appear as sseparate entities in search results.
SVGMath | MathJax HTML | MathJax SVG | KaTeX | |
---|---|---|---|---|
On initial load | ||||
DOM elements | 413 | 97 | 97 | 97 |
kB transferred | 181 | 282 | 760 | 92.8 |
DOM Content Loaded | 0.179 s | 2.30 s | 0.98 s | 2.10 s |
kB resources | 181 | 1300 | 2,500 | 460 |
Fully loaded and processed | ||||
DOM elements | 3604 | 9,551 | 11,086 | 12,869 |
kB transferred | 127 | 409 | 950 | 163 |
kB resources | 502 | 1,300 | 3,500 | 465 |
Duration | NA | 3.31 s | 2.30 s | 3.40 s |
Lighthouse performance score | 100 | 71 | 73 | 82 |
GTMetrix - blocking | 0 s | 0.629 s | 0.617 s | 0.225 s |
GTMetrix - time to interactive | 0.138 s | 1.1 s | 0.617 s | 0.625 |
(2) SVGs within <img> tags
Calling the SVGs in <img> tags produces the same low number of DOM elements (1/20 or less than the others) as <object>s.
However, we've had to use <path>s for all elements in the math (numbers and variables as well), since any <style> tags in the main page that target the SVG are ignored when called from an <img> tag. So the resource load is greater than the embedded SVG case (by about 4 times).
However, SVGs called by <img> tags is the best overall performance and SEO solution.
SVGMath | MathJax HTML | MathJax SVG | KaTeX | |
---|---|---|---|---|
On initial load | ||||
DOM elements | 410 | 97 | 97 | 97 |
kB transferred | 26.7 | 282 | 760 | 92.8 |
DOM Content Loaded | 1.07 s | 2.30 s | 0.98 s | 2.10 s |
kB resources | 220 | 1300 | 2,500 | 460 |
Fully loaded and processed | ||||
DOM elements | 522 | 9,551 | 11,086 | 12,869 |
kB transferred | 305 | 409 | 950 | 163 |
kB resources | 1,800 | 1,300 | 3,500 | 465 |
Duration | NA | 3.31 s | 2.30 s | 3.40 s |
Lighthouse performance score | 100 | 71 | 73 | 82 |
GTMetrix - blocking | 0 s | 0.629 s | 0.617 s | 0.225 s |
GTMetrix - time to interactive | 0.140 s | 1.1 s | 0.617 s | 0.625 |
(3) (Historical) SVGs within <object> tags
NOTE: Earlier, I had a version that used <object> tags. It proved to be unsatisfactory because the user experience was "clunky" (especially on a phone) as the math fonts have to be loaded for every <object>. Overall, I now feel the image tag approach is best.
Here are the stats for the <object> case.
The number of DOM elements required is least when using <img> or <object> tags (since we only require 2 for each piece of mathematics - a wrapper span and the one tag).
Here I'm using <text> tags in the SVG once again (to keep things as small as possible), but the downside is that the fonts need to be called in every SVG embedded this way. Browsers aren't bright enough to remember they've already accessed the font (even though Chrome's developer tools indicate the font is coming from the cache) so "download" it for each math item. So it indicates a huge resource load (6.8 MB) where in fact, the fonts are only loaded once.
The number of DOM elements is about 1/20 of MathJax's and KaTeX's.
This method also is problematic for SEO.
SVGMath | MathJax HTML | MathJax SVG | KaTeX | |
---|---|---|---|---|
On initial load | ||||
DOM elements | 420 | 97 | 97 | 97 |
kB transferred | 428 | 282 | 760 | 92.8 |
DOM Content Loaded | 0.239 s | 2.30 s | 0.98 s | 2.10 s |
kB resources | 503 | 1300 | 2,500 | 460 |
Fully loaded and processed | ||||
DOM elements | 529 | 9,551 | 11,086 | 12,869 |
kB transferred | 428 | 409 | 950 | 163 |
kB resources | 6800 | 1,300 | 3,500 | 465 |
Duration | NA | 3.31 s | 2.30 s | 3.40 s |
Lighthouse performance score | 100 | 71 | 73 | 82 |
GTMetrix - blocking | 0 s | 0.629 s | 0.617 s | 0.225 s |
GTMetrix - time to interactive | 0.108 s | 1.1 s | 0.617 s | 0.625 |
Finally
The SVGMath demo page was chosen because it has many equations, and label tags (equation numbering), and links to tags (which MathJax can handle, KaTeX cannot yet).