How to Add Math Equations to Astro with KaTeX
Astro can render mathematical equations in Markdown using KaTeX, a LaTeX renderer, allowing formulas to be generated as part of the website’s build process. This provides clean, properly formatted equations without requiring client-side JavaScript to render them in the browser. With a simple setup, Markdown files can render professional-looking equations directly.
This article covers how to:
- Enable math support in Astro.
- Install and configure the required plugins.
- Load the required styles.
- Write math in Markdown and MDX.
- Render equations with KaTeX.
Why Use KaTeX With Astro
KaTeX is a popular tool for rendering math on the web because it is:
- Fast and lightweight.
- Easy to configure.
- Well supported.
- Well suited to static sites.
When combined with Astro’s Markdown system, KaTeX renders equations at build time. This keeps the rendered equations in the generated HTML rather than requiring client-side math rendering. As an example, KaTeX is used on this website to explain the underlying equations for the Treasury Bill Yield Calculator.
KaTeX is often compared to MathJax, the other common choice for rendering LaTeX math on the web. MathJax supports a wider range of LaTeX commands and packages, but it is heavier and can run its rendering step in the browser rather than at build time, depending on configuration. KaTeX covers the LaTeX syntax most technical writing needs while keeping rendering entirely at build time, which is why it pairs well with a static site generator like Astro.
Configure Astro for Math Equations
Astro 7 changed its default Markdown processor from Unified to Sätteri. The Unified pipeline still works on Astro 7 and later, but it is no longer the default, and Sätteri does not accept Unified-style remark or rehype plugins directly. The setup differs depending on which processor the project uses. Readers on Astro 6 or earlier, or on Astro 7+ with the legacy pipeline enabled, should follow the Unified path. Readers on a default Astro 7+ install should follow the Sätteri path.
Unified Pipeline
This path applies to Astro 6 and earlier, and to Astro 7+ projects that opt into the legacy Unified processor.
Install Math Rendering Plugins
Install two packages to enable math rendering in Astro:
remark-mathparses LaTeX math syntax.rehype-katexrenders it with KaTeX.
rehype-katex depends on KaTeX, so installing rehype-katex also installs KaTeX. There is no need to install KaTeX separately for this pipeline.
Install both packages:
npm install remark-math rehype-katex
Configure Astro for Math Support
Next, configure Astro to use the Unified Markdown processor in astro.config.mjs.
import { defineConfig } from 'astro/config';
import { unified } from '@astrojs/markdown-remark';
import remarkMath from 'remark-math';
import rehypeKatex from 'rehype-katex';
export default defineConfig({
markdown: {
processor: unified({
remarkPlugins: [remarkMath],
rehypePlugins: [rehypeKatex]
})
},
});
This configuration instructs Astro to detect math expressions in Markdown and convert them into KaTeX-rendered HTML during build.
For cases that need MathJax’s broader LaTeX coverage, rehype-mathjax is a drop-in alternative to rehype-katex in this pipeline.
Sätteri Pipeline
This path applies to a default Astro 7+ install. Sätteri has no official KaTeX plugin, so this path uses a small custom plugin instead of an installed package.
Install KaTeX
Sätteri’s features: { math: true } option handles math parsing natively, so remark-math is not needed. Install KaTeX directly:
npm install katex
Write a Sätteri Math Plugin
Create a plugin file (plugins/satteri-katex.js) that renders math nodes with KaTeX.
AstroProject/
├── astro.config.mjs
├── package.json
├── plugins/
│ └── satteri-katex.js
└── src/
└── ...
import katex from 'katex';
import { defineMdastPlugin } from 'satteri';
const ESCAPES = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": ''',
};
const escapeHtml = (value) => value.replace(/[&<>"']/g, (c) => ESCAPES[c] ?? c);
const preserveBackslashes = (html) => html.replace(/\\/g, '\\\\');
export function satteriKatex(options = {}) {
const katexOptions = { output: 'htmlAndMathml', throwOnError: true, ...options };
const render = (tex, displayMode) => {
try {
const rendered = katex.renderToString(tex, { ...katexOptions, displayMode });
return { raw: preserveBackslashes(rendered), mdxExpressions: false };
} catch (error) {
return { raw: preserveBackslashes(escapeHtml(String(error))), mdxExpressions: false };
}
};
return defineMdastPlugin({
name: 'satteri-katex',
math(node) {
return render(node.value, true);
},
inlineMath(node) {
return render(node.value, false);
},
});
}
The plugin returns { raw, mdxExpressions: false } rather than a plain string or a new mdast node. This is Sätteri’s node-splicing shape. The raw string is re-parsed in place of the visited node, and mdxExpressions: false prevents curly braces in the KaTeX output from being read as MDX expressions.
Because the raw string is re-parsed, a literal backslash inside it would be interpreted as a Markdown escape character. KaTeX’s MathML output embeds the original LaTeX source in an annotation element, which may contain backslashes (\int, \infty). preserveBackslashes doubles each one so it survives the re-parse and comes out as a single backslash in the final HTML.
The escapeHtml step in the catch branch matters because the failed input is the reader’s own LaTeX source, which may contain characters like < or & from comparison operators or set notation. Escaping it before returning ensures a malformed equation shows up as visible error text rather than being interpreted as HTML.
Configure Astro for Math Support
Wire the plugin into astro.config.mjs, enabling Sätteri’s native math parsing and passing the plugin as an MDAST plugin.
import { defineConfig } from 'astro/config';
import { satteri } from '@astrojs/markdown-satteri';
import { satteriKatex } from './plugins/satteri-katex.js';
export default defineConfig({
markdown: {
processor: satteri({
features: { math: true },
mdastPlugins: [satteriKatex]
}),
},
});
Sätteri’s math feature parses a single $ as the start of inline math by default, which means literal currency text like $50 to $100 renders as broken math instead of plain text. If the content mixes math with currency, disable single-dollar parsing while keeping block math intact:
processor: satteri({
features: { math: { singleDollarTextMath: false } },
mdastPlugins: [satteriKatex({ throwOnError: false })]
})
With this option set, $$ ... $$ still renders as math, and a lone $ is treated as literal text.
With Sätteri’s default math handling, a malformed equation is rendered as plain text rather than causing the build to fail. Passing { throwOnError: false } to satteriKatex() switches the plugin to KaTeX’s non-throwing error rendering instead.
Add KaTeX Styles
KaTeX requires CSS to display equations correctly. Without it, formulas will appear unstyled or broken.
There are several ways to load the styles, depending on how often the website includes math content.
Importing CSS locally reduces unnecessary page weight for websites that use math in only a few posts. A global import is more practical when many pages use math.
Option 1: Import in Markdown
Importing the KaTeX stylesheet directly from an individual content file requires an .mdx file.
import 'katex/dist/katex.min.css';
This keeps the KaTeX CSS associated with pages that import it.
Option 2: Import in a Main Layout
KaTeX can also be imported in a shared layout file:
---
import 'katex/dist/katex.min.css';
---
All pages using this layout will include the styles.
Option 3: Import in a Global CSS File
For websites using global styles, add:
@import 'katex/dist/katex.min.css';
All pages using this global stylesheet will include the KaTeX styles.
Write Math in Markdown
Once setup is complete, Markdown files can include math directly using LaTeX syntax. The same $ and $$ syntax works unchanged in .mdx files.
Inline Math
Use single dollar signs for inline equations (unless the Sätteri pipeline has singleDollarTextMath: false set, as described earlier):
Mass-energy equivalence (Einstein’s formula) is $E = mc^2$.
Which renders as:
Mass-energy equivalence (Einstein’s formula) is .
This renders the equation inside the sentence and keeps the text flowing naturally.
Block Math
Use double dollar signs for centered equations:
$$
\int_0^\infty e^{-x^2} dx = \frac{\sqrt{\pi}}{2}
$$
Which renders as:
Block math is best for longer or more complex formulas that require visual emphasis.
Accessibility
KaTeX output also supports accessibility. KaTeX includes MathML alongside its visual rendering, providing a semantic representation that can be used by browsers and assistive technologies. No additional configuration is required to include this MathML output.
Summary
Astro can render mathematical equations in Markdown using KaTeX, providing clean, professional math without requiring client-side rendering. The setup requires a small amount of configuration and then the equations are rendered during the website’s build process on either pipeline. Once configured, the remaining work is simply writing equations using standard KaTeX syntax.