FxEditor
User guideQuickstartDeploymentAPIDesignFxTeX
APIExamplesAccessibility
FxTeXServer
DeploymentAPILaTeXRender
DeploymentAPIPlugins
CK Editor v5Tiny MCE v6BloggerAngularDeveloper GuideLicensing
How licensing worksfxTeX
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 is the renderer only. If you want an editing surface for your users, that is fxEditor; if you want the same conversion done server-side, that is fxTeXServer. All three run the same converter, so all three produce the same MathML for the same input.
Installation
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.
Everything below is about the cases that are not common: scanning part of a page, scanning a different set of delimiters, controlling whether equation images are ever fetched, and re-scanning after your own code changes the page.
The bundle is 30 kB as your reader downloads it, gzipped; 100 kB
on disk. There are no fonts to download alongside it and no second request for a stylesheet
— the CSS is inside the bundle. It has no dependencies and defines exactly one global,
window.fxTeX.
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.
Choosing how it scans
There are two scans, and three entry points that run them:
| Call | Runs |
|---|---|
fxTeX.render(options) | both scans, immediately |
fxTeX.renderText(options) | the delimiter scan only |
fxTeX.renderImages(options) | the equation-image scan only |
fxTeX.autoRender(options) | render(), once the DOM is ready |
All four take the same options object:
fxTeX.render({
root: document.getElementById('article'), // default: document.body
delimiters: fxTeX.DEFAULT_DELIMITERS, // $ and $$ only
ignoreSelector: 'script, style, textarea, pre, code, noscript, math, .no-cc-render',
text: true, // false skips the delimiter scan entirely
images: { // false skips the image scan entirely
imgSelector: 'img[src*="codecogs.com/svg.image"]',
dataImgSelector: 'img[data-latex-src], img[data-latex]',
templateSelector: 'template.cc-equation'
},
speech: fxTeX.WRAPPER_LABEL, // how spoken text is attached (default WRAPPER_LABEL)
onError: function (source, err) { console.warn('Could not render', source, err); }
});
root — the subtree to scan. Narrowing it is the main performance control: a page whose equations all live inside one article element has no reason to walk its navigation, footer and comment thread. It is also how you re-render just the part of a page your own code has changed.
delimiters — an array of
{ left, right, display }. display: true is a centred block,
false is inline. Longer delimiters win ties, so $$ is always read as a
block and never as two empty $ pairs. Supplying this option replaces the default set
rather than adding to it, which is why the opt-in line above spreads
DEFAULT_DELIMITERS back in.
ignoreSelector — a CSS selector. Any element matching it
is skipped, and so is everything inside it. Replace the default if you need a different exclusion
— a documentation site that writes its samples in <samp>, say — and
keep math in whatever you replace it with, or a second render() call
will try to convert output from the first.
text — set false on a page whose equations
are all images. It skips building the text walker at all, which is cheaper than running one over
text that was never going to match.
images — set false on a page that has no
equation images, or pass an object to change which elements count as one. The three selectors are
described in the next section.
speech — how each equation's spoken text is attached for
screen readers. On by default as fxTeX.WRAPPER_LABEL; set one of four values:
fxTeX.WRAPPER_LABEL(1) — the speech becomes the accessible name of a span around the equation, so a reader announces the name instead of descending into the MathML. The default, and the one observed to work most widely.fxTeX.HIDDEN_SPAN(2) — the MathML is left for readers that speak it natively, with the text beside it in a visually-hidden span.fxTeX.ARIA_LABEL(3) — the text is anaria-labelon the<math>element itself.fxTeX.OFF(0) — no spoken text; plain MathML, read by whatever native support the browser and screen reader have between them.
Which one to pick, and what each sounds like in a real screen reader, is on the
accessibility bench — a live page you can switch
between the modes on, not a description of them. convertToMathML() is the one
exception to the default: it returns plain MathML with no speech, being the raw one-string
convert.
onError — called with
(source, error) for any equation that fails to parse. Without it a malformed equation
is left exactly as it was written and the scan carries on; one bad equation never takes down the
rest of the page.
Scanning only part of a page
The two together — a narrow root and images: false — are
the usual shape for a page that knows where its maths is:
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') });
});
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.
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 the markup genuinely cannot be touched
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.
For conversion inside an existing C++, PHP or Python service rather than a JavaScript one, see fxTeXServer.
Reference
Everything on window.fxTeX:
| Member | What it does |
|---|---|
render(options?) | Runs the image scan and the text scan. Safe to call repeatedly. |
renderText(options?) | The delimiter scan only. Returns early if text: false. |
renderImages(options?) | The equation-image scan only. Returns early if images: false. |
autoRender(options?) | render() now if the DOM is parsed, otherwise on DOMContentLoaded. |
convertToMathML(latex, display?) | Converts one string and returns MathML. No DOM involved. |
blockRemoteImages() | CSP-based suppression of equation-image requests. See the caveat above. |
isCodeCogsUrl(url) | Whether a URL is a CodeCogs rendering endpoint. |
extractLatexFromQueryUrl(url) | The LaTeX out of such a URL, with CodeCogs' own escaping undone. |
DEFAULT_DELIMITERS | $$...$$ and $...$. |
LATEX_BRACKET_DELIMITERS | \[...\] and \(...\). Not scanned unless you add them. |
WRAPPER_LABEL / HIDDEN_SPAN / ARIA_LABEL / OFF | 1 / 2 / 3 / 0 — the values the speech option takes. |
Options, with their defaults:
| Option | Default | Meaning |
|---|---|---|
root | document.body | Subtree to scan. |
delimiters | DEFAULT_DELIMITERS | Replaces the set, does not extend it. |
ignoreSelector | script, style, textarea, pre, code, noscript, math, .no-cc-render | Skipped, along with descendants. |
text | true | false skips the delimiter scan. |
images | {} | false skips the image scan; an object overrides its selectors. |
speech | WRAPPER_LABEL | How spoken text is attached: WRAPPER_LABEL / HIDDEN_SPAN / ARIA_LABEL / OFF. |
images.imgSelector | the four codecogs.com rendering endpoints | Live <img src> tags. |
images.dataImgSelector | img[data-latex-src], img[data-latex] | Never-fetched <img> tags. |
images.templateSelector | template.cc-equation, template[data-cc-equation] | Wrapped <img> tags. |
onError | none | Called per failed equation; the scan continues either way. |
Every equation fxTeX produces carries generated speech alongside its MathML, in the mode the
speech option chooses (default fxTeX.WRAPPER_LABEL; see above). What
each mode sounds like in a real screen reader is on the
accessibility bench — a live page, not a
report.
More
Accessibility — a live bench showing what a screen reader says for each equation.
fxTeXServer — the same converter run on your own server, in C++, Node or Docker.
fxEditor — if your users need to write the equations as well as read them.
How we compare — against KaTeX, MathJax and Temml.
CodeCogs®