As far as I am aware, there is no HTML-only way to detect support for MathML.
However, there is an SVG way.
The <switch>
SVG element renders the first direct child of itself where certain boolean attributes on that child are either missing or evaluate to true. One such attribute is the requiredExtensions
attribute, which mandates that the user agent has to support a particular extension to render the indicated element.
So, if you have an SVG <foreignObject>
element (used to embed non-SVG elements in SVG) with requiredExtensions="http://www.w3.org/1998/Math/MathML"
set on it, and then put that <foreignObject>
inside a <switch>
element, the <math>
element will be rendered if MathML is supported, and the next element will be if MathML isn't.
So, for a basic MathML example: <math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn><mo>+</mo><mn>1</mn><mo>=</mo><mn>2</mn></math>
is MathML for 1 + 1 = 2.
A basic SVG fallback for this would be <svg xmlns="http://www.w3.org/2000/svg" width="65" height="23"><text y="15" font-size="16">1 + 1 = 2</text></svg>
(more complicated fallbacks could be generated with Mathjax-Node).
So the completed MathML expression with fallback would be:
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="120" height="40">
<switch>
<foreignObject requiredExtensions="http://www.w3.org/1998/Math/MathML" width="120" height="40">
<math xmlns="http://www.w3.org/1998/Math/MathML">
<mn>1</mn><mo>+</mo><mn>1</mn><mo>=</mo><mn>2</mn><mtext>MathML</mtext>
</math>
</foreignObject>
<text y="15" font-size="16">1 + 1 = 2 (SVG)</text>
</switch>
</svg>
I have tested the above in Firefox (renders MathML), Edge, IE11 and Chrome (renders SVG). I have not tested Safari, as I don't own a Mac.
EDIT: Safari 9 renders the MathML.
But I want to support IE8!
Why?
BECAUSE!
Fine.
If you want to keep the ability to copy + past your math, you can't use an <picture>
tag to embed your SVG/MathML hybrid - use <object>
instead:
(I'm using a DataUrl here, but you could just as easily save the SVG as an external file):
<object typemustmatch type="image/svg+xml" data="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4NCjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB3aWR0aD0iMTIwIiBoZWlnaHQ9IjQwIj4NCiAgPHN3aXRjaD4NCiAgICA8Zm9yZWlnbk9iamVjdCByZXF1aXJlZEV4dGVuc2lvbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTgvTWF0aC9NYXRoTUwiIHdpZHRoPSIxMjAiIGhlaWdodD0iNDAiPg0KICAgICAgPG1hdGggeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTgvTWF0aC9NYXRoTUwiPg0KICAgICAgICA8bW4+MTwvbW4+PG1vPis8L21vPjxtbj4xPC9tbj48bW8+PTwvbW8+PG1uPjI8L21uPjxtdGV4dD5NYXRoTUw8L210ZXh0Pg0KICAgICAgPC9tYXRoPg0KICAgIDwvZm9yZWlnbk9iamVjdD4NCiAgICA8dGV4dCB5PSIxNSIgZm9udC1zaXplPSIxNiI+MSArIDEgPSAyIChTVkcpPC90ZXh0Pg0KICA8L3N3aXRjaD4NCjwvc3ZnPg==">
1 + 1 = 2 (You don't support SVG)
</object>
(You could render the SVG as a PNG using CloudConvert or similar and put in inside the object if you really wanted.)
So there you go. A little pre-rendering, and you have a MathML fallback that requires no JavaScript or CSS - just HTML.
EDIT: I have made an NPM package to automate the creation of the MathML, SVG, and PNG. It can be found here.