From Markdown to Mathematics: LaTeX in SvelteKit and MDSveX

One of the requirements I set myself when building this blog was that it must support LaTeX. This post shows how I achieved turning this “e=mc^2” into e=mc2e=mc^{2} . Besides inline math, blocks are supported as well which turns “F=G(m1m2/r^2)” into

F=G(m1m2r2)F=G(\\frac{m_1m_2}{r^2})

If you’re looking to integrate LaTeX into your website, this post should be a helpful starting point, especially if you’re using the markdown preprocessor MDSveX with SvelteKit.

Trying MathJax

At first, I gave MathJax a shot. Integration and configuration is an absolute breeze as you simply add a script tag for the source and optionally another for setting various options.

<script>
	window.MathJax = {
		tex: {
			inlineMath: [
				['$', '$'],
				['\\(', '\\)']
			],
			displayMath: [
				['$$', '$$'],
				['\\[', '\\]']
			],
			processEscapes: true
		}
	};
</script>

<script
	id="MathJax-script"
	async
	src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"
></script>

I can’t imagine any easier method if you want LaTeX support that simply works out of the box regardless of which frameworks you’re using.

There is a small downside however. Whenever the page has finished loading, you get a slight flicker as MathJax scans the page and replaces text with LaTeX. For websites with cookie banners, privacy consents, loads of ads, heavy analytics scripts, it likely won’t be a noticeable issue. But, since my website is light, fast and simple, it definitely became more noticeable.

Serverside rendering using MDSveX and KaTeX

Not quite being satisfied with the flicker, I turned to KaTeX, the self-proclaimed ”fastest math typesetting library for the web”. Since I’m using MDSveX, I went with the ‘official’ integration of KaTeX which is a rehype plugin.

The installation is straightforward. First you need to install the package rehype-katex-svelte using npm, yarn or similar. Then you must add the remarkMath and rehypeKatexSvelte plugin to your MDSveX configuration. Due to some issues with double rendering I had to explicitly require output as mathml instead of the default mathml + HTML (for accessibility). I didn’t delve deeper into the problem, but there’s certainly a better solution for keeping HTML.

import { defineMDSveXConfig as defineConf } from 'mdsvex';
import rehypeKatexSvelte from 'rehype-katex-svelte';
import remarkMath from 'remark-math';
...

const config = defineConf({
	remarkPlugins: [remarkMath],
	rehypePlugins: [
		[
			rehypeKatexSvelte,
			{
				output: 'mathml'
			}
		]
	]
});

The result is lightning fast and the flicker is completely eliminated due to server-side rendering

3/5/2024

© 2026 skottenborg.dev