fxTeX & fxTeX Pro
fxTeX is a single <script> you drop onto any page. It finds the LaTeX already
sitting in that page's own markup — $x^2$, $$x^2$$, and CodeCogs
equation <img> tags — and replaces each one, in place, with real MathML.
No server round-trip, and for three of the four forms below no image request either.
It comes in two versions that work the same way: the same two lines to put on a page, the same options and the same MathML out. fxTeX is free, with no key and no limit — it never contacts our servers to render. fxTeX Pro is the professional version: the same converter compiled to WebAssembly, for a site that is registered with us and opens it with a licence key.
| fxTeX | fxTeX Pro | |
|---|---|---|
| Licence | Free, no key | Professional or Enterprise; your site registered, opened with your licence key |
| Converting 57 equations | 5.7 ms | 2.1 ms |
| … with spoken text | 8.4 ms | 5.3 ms |
| LaTeX commands supported | 1,159 | 1,302 |
| Packages | mhchem, built in | mhchem, plus chemfig and physics |
| Download, gzipped | 43 kB | 110 kB |
| Equation editor | — | fxEditor included |
fxTeX Pro is built for pages with a lot of maths. It converts the 57 equations of our benchmark 2.7 times faster than fxTeX, and delivers them with spoken text 170 times faster than MathJax: 5.3 ms against 904 ms (see how we compare). Its download is larger, so it is on a page with plenty of equations that the speed pays off. It can also load extra packages — chemfig for chemical structures, physics for the LaTeX physics package — while mhchem, for chemical formulae, is in both. And it comes with the equation editor, fxEditor, for pages where your users write the maths as well as read it.
This page installs fxTeX, shows what it finds, and walks through the common tasks. Every function and option is in the API.
Every equation either renders also gets a right-click menu: your readers can copy it as LaTeX, MathML, SVG or PNG, open it in the equation editor, or turn it into a live graph and calculator.
If you want equations as image files, or in places where a script cannot run, that is fxTeX Server. fxTeX, fxEditor and fxTeX Server run the same converter, so all three produce the same MathML for the same input.
Installation
fxTeX
Two lines. The second one starts the scan.
<script src="https://fxtex.codecogs.com/fxtex.min.js"></script>
<script>fxTeX.autoRender();</script>
autoRender() scans document.body and runs immediately if the DOM has
already been parsed, or on DOMContentLoaded if it has not. The script also injects the
small amount of CSS its own MathML output needs, so there is no stylesheet to add. That is the
whole setup for the common case.
The bundle is 43 kB as your reader downloads it, gzipped; 139 kB
on disk. There is no second request for a stylesheet — the CSS is inside the bundle —
and one font, New Computer Modern Math (683 kB), fetched from beside the script for a page
with an equation on it and kept by the browser after that. It has no dependencies and defines exactly one global,
window.fxTeX.
fxTeX Pro
fxTeX Pro is the same converter compiled to WebAssembly and built for your licence: it renders exactly the same MathML, faster. It is part of the Professional and Enterprise licences, and each build is locked to your domain and opened with your licence key. The lines to add are in the licence manager, with your key already filled in:
<script src="https://fxtex.codecogs.com/fx_pk_your-key-here/fxtexpro.min.js"></script>
<script>
fxTeXPro.ready.then(() => {
fxTeXPro.unlock('fx_pk_your-key-here');
fxTeXPro.autoRender();
});
</script>
Everything on this page applies unchanged, on the fxTeXPro global rather than
fxTeX, with one difference: the WebAssembly loads asynchronously, so wait on
fxTeXPro.ready before calling render() or convertToMathML()
(autoRender() waits by itself). unlock() returns 'ok', or
'bad-key', 'domain' or 'expired' saying why not; until it
succeeds, equations show that reason in place of the maths — see
Setup. See licence
options.
What it finds
Four ways an equation can be written into a page, and whether each is scanned without you asking:
| Written as | Renders as | Scanned by default |
|---|---|---|
$x^2$ | inline | yes |
$$x^2$$ | display (block) | yes |
\(x^2\) | inline | no — opt in |
\[x^2\] | display (block) | no — opt in |
<img src="https://latex.codecogs.com/svg.image?x^2"> | whatever the URL's own \inline says | yes |
<img data-latex="x^2"> | same | yes |
<template class="cc-equation"> | same | yes |
Only $ and $$ are scanned by default. \(...\) and
\[...\] work, but you have to ask for them — a smaller default is one fewer way
to convert a stray \[ in ordinary prose that was never meant to be an equation. One
line adds them back:
fxTeX.render({
delimiters: [...fxTeX.DEFAULT_DELIMITERS, ...fxTeX.LATEX_BRACKET_DELIMITERS]
});
Here is the default set running against this page. The box below contains nothing but the text you see quoted under it:
Source: The quadratic $ax^2+bx+c=0$ has roots $$x=\frac{-b\pm\sqrt{b^2-4ac}}{2a}$$ which are real when $b^2\ge 4ac$.
Text inside <script>, <style>,
<textarea>, <pre>, <code>,
<noscript>, an already-converted <math>, or any element
carrying the class no-cc-render is left alone. That list is the default value of
ignoreSelector, and you can
replace it.
Common tasks
Each of these is a call to render()
or one of its relatives, with an option
or two.
Scanning only part of a page
A narrow root and images: false are the usual shape for a page that
knows where its maths is — there is no reason to walk the navigation, footer and comment
thread:
fxTeX.render({ root: document.querySelector('main article'), images: false });
Re-scanning after the page changes
render() is safe to call as often as you like. Already-converted equations are
<math> elements, which the default ignoreSelector excludes, so a
second pass never double-converts anything. After a route change or an Ajax insert, point
root at just the new content:
router.afterEach(function () {
fxTeX.render({ root: document.getElementById('view') });
});
Making equations larger or smaller
For every equation on a site, one rule in your own stylesheet; for one render, the
fontSize option. Either takes any CSS
font size:
:root { --fxtex-font-size: 120%; } /* every equation on the page */
fxTeX.render({ root: document.getElementById('worked-example'), fontSize: '140%' });
Converting a string you already have
If you are not scanning a page at all — you are building markup yourself, or converting LaTeX that arrived from your own server — skip the DOM layer:
fxTeX.convertToMathML('\\frac{1}{2}'); // inline
fxTeX.convertToMathML('\\frac{1}{2}', true); // display
It returns a MathML string. Nothing is inserted anywhere; what you do with it is your business. fxTeX Pro can also hand you the converter itself, for spoken text, a font size and other settings — see converter().
Drawing equations as SVG
MathML is drawn by the browser, and browsers draw it a little differently. fxTeX Pro can draw each equation itself instead, as SVG that looks the same everywhere:
fxTeXPro.autoRender({ format: 'svg' });
See SVG output.
Trimming the right-click menu
fxTeX Pro can cut the right-click menu down for the whole page — to the Copy items only, or to nothing at all:
fxTeXPro.autoRender({ contextMenu: { mode: 'copy' } }); // 'full' (default), 'copy' or 'disable'
Equation images
An <img> whose src carries the LaTeX in its query string —
CodeCogs' own svg.image, png.image, gif.latex and
png.latex endpoints, and anything else using the same convention — is read,
converted, and swapped for the equivalent <math>. Any class or
id on the original is carried across, so CSS that already targets your equations keeps
working.
Three ways to write one. They differ in a single respect: whether the browser ever actually requests the image.
1. A live <img src> — no markup change, but the request has already gone
<img src="https://latex.codecogs.com/svg.image?\frac{1}{2}">
fxTeX finds it, converts it, replaces it — on an existing page, with nothing edited. But by the time any script runs, the browser's preload scanner has already asked for that image. Nothing running after parsing begins can call it back. That is how browsers parse HTML, not a limitation here. If the request itself matters — bandwidth, a rate-limited image host, or simply that a page full of MathML should not also be quietly fetching pictures of it — use one of the next two.
2. data-latex — no request, smallest change
<img data-latex-src="https://latex.codecogs.com/svg.image?\frac{1}{2}">
<!-- or, skipping the URL entirely: -->
<img data-latex="\frac{1}{2}">
No src attribute, so there is nothing for the browser to fetch — guaranteed,
not merely unlikely. If your equation markup comes out of a server template this is usually a
one-line change to whatever currently writes src="...".
data-latex, with no network request.
3. A <template> wrapper — no request, no attribute rename
<template class="cc-equation">
<img src="https://latex.codecogs.com/svg.image?\frac{1}{2}">
</template>
A <template>'s content is inert by specification: nothing inside it is
fetched while it sits there. The original <img src> markup is kept exactly as
it was, just wrapped — which is often an easier find-and-replace than renaming an attribute,
and leaves the src readable by anything else that wants it.
If you cannot change the markup
fxTeX.blockRemoteImages() exists for pages stuck with live, unrenameable
<img src> tags. Read the caveat before reaching for it: CSP's
img-src is an allow-list, not a block-list. There is no way to say "block this one
host", so using it means listing every other image host your page relies on, or every
other image on the page stops loading too. Options 2 and 3 have no such caveat and are the ones
we would recommend.
Timing and first paint
Conversion is synchronous. There is no worker, no promise and no async setup: for an ordinary page — tens to a few hundred equations — the whole scan finishes inside a single frame. That has a useful consequence, which is that you can decide exactly when it happens.
autoRender() waits for DOMContentLoaded, which fires after the DOM is
built but before images and stylesheets finish, and is early enough that most pages never show
un-rendered source. It deliberately does not hide your page to guarantee that — a blank page
until JavaScript finishes is a real cost, and should be something you choose. If you do want to
guarantee it, the pattern is the one web-font loaders use:
<head>
<style>body { visibility: hidden; }</style>
<script src="https://fxtex.codecogs.com/fxtex.min.js"></script>
</head>
<body>
...
<script>
fxTeX.render();
document.body.style.visibility = 'visible';
</script>
</body>
Because render() is synchronous, the page becomes visible on the line after the
equations are already MathML. There is no race and no flicker to tune.
Rendering server-side
The bundle imports cleanly under Node — the stylesheet injection is guarded on
document existing — so convertToMathML() can run in a build step or
a request handler. There is no document to inject CSS into in that case, so link the
stylesheet that ships alongside the bundle:
<link id="fxtex-style" rel="stylesheet" href="https://fxtex.codecogs.com/fxtex.css">
Give it that id. If the page later loads fxtex.min.js as well —
to pick up LaTeX added on the client after an SSR page load — the script looks for exactly
that id and skips injecting a second, identical copy of the rules.
From a service that is not written in JavaScript, ask
fxTeX Server for mathml
instead — the markup is identical.
Packages
fxTeX Pro only. Some packages are left out unless you ask for them, so a page that does not use them neither downloads them nor converts their commands. There are three, each with a page of its own:
mhchem — chemical formulae, equations and units,
\ce and \pu. (fxTeX has it built in.)
chemfig — chemical structures and reaction schemes,
\chemfig, \schemestart and the rest, drawn as SVG.
physics — the LaTeX physics package's \qty,
\dv, \pdv, \mqty, \vb and the rest of the
commands fxTeX does not already have built in.
Name the packages you want, either to autoRender() or, before rendering, to
usePackages():
fxTeXPro.ready.then(() => {
fxTeXPro.unlock('fx_pk_your-key-here');
fxTeXPro.autoRender({ packages: ['physics', 'chemfig'] });
});
// or, rendering yourself
await fxTeXPro.ready;
fxTeXPro.unlock('fx_pk_your-key-here');
await fxTeXPro.usePackages(['physics', 'chemfig']);
fxTeXPro.render();
usePackages() fetches each package from beside fxtexpro.min.js and
resolves once its commands are ready, so render after it. Until then, and on any page that never
asks, a package's commands are unknown, like any other unknown command. The equation editor takes the same list: EqEditor.init({ licence, packages: ['chemfig'] }). Every package and its
commands are listed under Supported commands.
More
API — every function and option, for fxTeX and fxTeX Pro.
Accessibility — a live bench showing what a screen reader says for each equation.
Right-click menu — copying equations, and the graph and calculator.
Supported commands — every LaTeX command fxTeX reads, each with an example.
fxTeX Server — the same converter as a URL, for SVG, PNG, PDF and MathML.
fxEditor — if your users need to write the equations as well as read them.
Plugins — fxEditor inside the editors and platforms your site already uses.
Packages — mhchem, chemfig and physics: what each adds, and how to turn them on.
How we compare — against KaTeX, MathJax and Temml.
