KaTeX is a web-based mathematics typesetting library, similar to the erstwhile untouchable MathJax. Unfortunately, out of the box, KaTeX only supports one font, its default Computer Modern-based font, and does not have built-in functionality for customising this. Thankfully, it is not difficult to achieve this.

KaTeX defines a table of symbols, which specifies what font to use for each symbol. We can use katex.__defineSymbol to change the font used for alphanumeric text (defined in KaTeX's symbols.js), before rendering any mathematics:

// All of these are textords in math mode
const mathTextSymbols = "0123456789/@.\"";
for (let i = 0; i < mathTextSymbols.length; i++) {
	const ch = mathTextSymbols.charAt(i);
	katex.__defineSymbol("math", "custom", "textord", ch, ch);

// All of these are textords in text mode
const textSymbols = "0123456789!@*()-=+\";:?/.,";
for (let i = 0; i < textSymbols.length; i++) {
	const ch = textSymbols.charAt(i);
	katex.__defineSymbol("text", "custom", "textord", ch, ch);

// All of these are textords in text mode, and mathords in math mode
const letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
for (let i = 0; i < letters.length; i++) {
	const ch = letters.charAt(i);
	katex.__defineSymbol("math", "custom", "mathord", ch, ch);
	katex.__defineSymbol("text", "custom", "textord", ch, ch);

This sets the requested font for alphanumeric characters to custom. Because KaTeX does not know about this font, it will raise an error because it cannot find the font metrics for custom, so we initialise them before rendering anything:

katex.__setFontMetrics("custom-Regular", {});
katex.__setFontMetrics("Math-Italic", {}); // makeOrd turns all mathematics into "Math-Italic" regardless of requested font
katex.__setFontMetrics("AMS-Regular", {}); // mathsym turns "custom" font into "ams"

// Now we can render the mathematics
renderMathInElement(document.body, {});

Now we can apply some CSS to set the custom font to whatever we like, e.g. Roboto:

.katex .mathnormal, .katex .mathrm, .katex .custom-Regular, .katex .amsrm {
	font-family: Roboto;

This results in:

This is almost correct, but because we did not provide the correct font metrics, the hat accents (^) are misplaced, and too close to the β's. We can use a simple Python script, based on KaTeX's extract_ttfs.py, to extract the correct metrics from our font:

CHARS_TO_EXTRACT = '\u0020\u00a0' # space/nbsp
CHARS_TO_EXTRACT += 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@*()-=+\";:?/.,'
CHARS_TO_EXTRACT += '\u03b1\u03b2\u03b3\u03b4\u03f5\u03b6\u03b7\u03b8\u03b9\u03ba\u03bb\u03bc\u03bd\u03be\u03bf\u03c0\u03c1\u03c3\u03c4\u03c5\u03d5\u03c7\u03c8\u03c9\u03b5\u03d1\u03d6\u03f1\u03c2\u03c6' # Lowercase Greek letters

from fontTools.ttLib import TTFont
import json
import sys

result = {}

fontInfo = TTFont('/path/to/font.ttf')
glyf = fontInfo['glyf']
widths = fontInfo.getGlyphSet()
unitsPerEm = float(fontInfo["head"].unitsPerEm)

cmap = [t.cmap for t in fontInfo["cmap"].tables
	if (t.platformID == 0)
	or (t.platformID == 3 and t.platEncID in (1, 10))]

for char in CHARS_TO_EXTRACT:
	code = ord(char)
	names = set(t.get(code) for t in cmap if t.get(code) is not None)
	if not names:
			"Codepoint {}, '{}' maps to no name\n"
			.format(code, char))
	if len(names) != 1:
			"Codepoint {}, '{}' maps to multiple names: {}\n"
			.format(code, char, ", ".join(sorted(names))))
	name = names.pop()
	height = depth = italic = skew = width = 0
	glyph = glyf[name]
	if glyph.numberOfContours:
		height = glyph.yMax / unitsPerEm
		depth = -glyph.yMin / unitsPerEm
	width = widths[name].width / unitsPerEm
	result[str(code)] = [depth, height, italic, skew, width]

print('const customMetrics = {};'.format(json.dumps(result)))

We can then pass the correct metrics to KaTeX before rendering anything:

const customMetrics = { ... };
katex.__setFontMetrics("custom-Regular", customMetrics);
katex.__setFontMetrics("Math-Italic", customMetrics);
katex.__setFontMetrics("AMS-Regular", customMetrics);

renderMathInElement(document.body, {});

A demonstration is shown below.


Built-in KaTeX font (Computer Modern):



Times New Roman:

Comic Sans: