Skip to content

Math

@beta

Render LaTeX math using KaTeX, with built-in support for chemistry notation via the mhchem extension.


Quick Start

from faststrap import Math

# Inline math
Math(r"\frac{a}{b}")

# Display math
Math(r"\int_{-\infty}^{\infty} e^{-x^2} dx", display_mode=True)

# Chemistry
Math(r"\ce{2H2 + O2 -> 2H2O}")

# Physics
Math(r"F = G \frac{m_1 m_2}{r^2}")

Features

  • LaTeX math rendering via KaTeX
  • Chemistry support through mhchem (\ce{}, \cee{}, reaction arrows)
  • Inline (<span>) and display (<div>) modes
  • Optional error throwing for unsupported LaTeX
  • Auto-renders on page load and after HTMX swaps
  • Theme-aware via set_component_defaults()

Parameters

Parameter Type Default Description
latex str required LaTeX math source.
display_mode bool False Render as block-level display math.
throw_on_error bool False Raise on unsupported LaTeX instead of rendering fallback text.
renderer str "katex" Rendering backend. Currently only "katex" is supported.
**kwargs Any Extra HTML attributes for the wrapper element.

Usage Examples

Inline Math

from fasthtml.common import SectionHeader
from faststrap import Math

SectionHeader(
    "Physics",
    subtitle=(
        "Newton's law: "
        + Math(r"F = G \frac{m_1 m_2}{r^2}")
        + " governs gravitational attraction."
    ),
)

Display Math

from faststrap import Card, Math

Card(
    Card.Header("Gaussian Integral"),
    Card.Body(
        Math(
            r"\int_{-\infty}^{\infty} e^{-x^2} dx = \sqrt{\pi}",
            display_mode=True,
        )
    ),
)

Chemistry Reactions

from faststrap import Card, Math

Card(
    Card.Header("Combustion"),
    Card.Body(
        Math(r"\ce{2H2 + O2 -> 2H2O}"),
        Math(r"\Delta H = -286 \text{ kJ/mol}", display_mode=True),
    ),
)

Biology Statistics

Math(r"p = \frac{n}{N} \times 100", cls="text-success")
Math(r"\bar{x} = \frac{1}{n}\sum_{i=1}^{n} x_i", display_mode=True)

Matrices and Linear Algebra

Math(
    r"A = \begin{pmatrix} a & b \\ c & d \end{pmatrix}",
    display_mode=True,
)

With Markdown Documents

Math components can be embedded inside Markdown output:

from faststrap import Markdown, Math

content = Markdown(
    "# Kinematics\n"
    + Math(r"s = ut + \frac{1}{2}at^2", display_mode=True)
)

When using Markdown with LaTeX, ensure KaTeX auto-render is configured to scan .faststrap-markdown containers as well as .faststrap-math.


Subject-Specific Patterns

Subject Example
Physics Math(r"\vec{F} = m\vec{a}")
Chemistry Math(r"\ce{H2SO4 + 2NaOH -> Na2SO4 + 2H2O}")
Math Math(r"\frac{d}{dx}\left( x^2 \right) = 2x", display_mode=True)
Biology Math(r"P(A|B) = \frac{P(B|A)P(A)}{P(B)}")

Configuration

Global Defaults

from faststrap import set_component_defaults

set_component_defaults("Math", display_mode=True, throw_on_error=True)

KaTeX CSS and JS

Faststrap does not inject KaTeX automatically. Include it in your app:

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.css">
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.js"></script>
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/contrib/auto-render.min.js"></script>

Or load via add_bootstrap() app headers.


When to Use Math vs Markdown

Use Case Component
Inline formulas in text Math
Display equations Math(display_mode=True)
Full documents with formulas Markdown + KaTeX auto-render
Chemistry reactions Math with mhchem syntax
Editable math input MathLive (external)

Accessibility

KaTeX output is accessible by default. For additional screen-reader support, consider pairing with MathJax's MathML output for complex documents.


API Reference

faststrap.components.display.math.Math(latex, *, display_mode=UNSET, throw_on_error=UNSET, renderer='katex', **kwargs)

Render LaTeX math using KaTeX.

Supports chemistry notation via the mhchem extension (\ce{}, \cee{}, reaction arrows, etc.).

Requires KaTeX to be loaded in the page. Faststrap does not inject KaTeX automatically; include it in your app assets or use a CDN.

Parameters:

Name Type Description Default
latex str

LaTeX math source.

required
display_mode bool | None

Render as block-level display math when True.

UNSET
throw_on_error bool | None

Raise on unsupported LaTeX instead of rendering the source as fallback text.

UNSET
renderer str

Rendering backend. Only "katex" is supported currently; "mathjax" is reserved for future use.

'katex'
**kwargs Any

Additional HTML attributes for the wrapper element.

{}

Returns:

Type Description
Div | Span

FastHTML Span for inline math or Div for display math,

Div | Span

containing delimited LaTeX for KaTeX auto-rendering.

Examples:

Basic math:

>>> Math(r"rac{a}{b}")

Display mode:

>>> Math(r"\int_{-\infty}^{\infty} e^{-x^2} dx", display_mode=True)

Chemistry:

>>> Math(r"\ce{2H2 + O2 -> 2H2O}")

Physics:

>>> Math(r"F = G rac{m_1 m_2}{r^2}")
Source code in src/faststrap/components/display/math.py
@register(category="display", requires_js=True)
@beta
def Math(
    latex: str,
    *,
    display_mode: bool | None = UNSET,
    throw_on_error: bool | None = UNSET,
    renderer: str = "katex",
    **kwargs: Any,
) -> Div | Span:
    """Render LaTeX math using KaTeX.

    Supports chemistry notation via the mhchem extension
    (``\\ce{}``, ``\\cee{}``, reaction arrows, etc.).

    Requires KaTeX to be loaded in the page. Faststrap does not
    inject KaTeX automatically; include it in your app assets or
    use a CDN.

    Args:
        latex: LaTeX math source.
        display_mode: Render as block-level display math when True.
        throw_on_error: Raise on unsupported LaTeX instead of rendering
            the source as fallback text.
        renderer: Rendering backend. Only ``"katex"`` is supported
            currently; ``"mathjax"`` is reserved for future use.
        **kwargs: Additional HTML attributes for the wrapper element.

    Returns:
        FastHTML ``Span`` for inline math or ``Div`` for display math,
        containing delimited LaTeX for KaTeX auto-rendering.

    Examples:
        Basic math:

        >>> Math(r"\frac{a}{b}")

        Display mode:

        >>> Math(r"\\int_{-\\infty}^{\\infty} e^{-x^2} dx", display_mode=True)

        Chemistry:

        >>> Math(r"\\ce{2H2 + O2 -> 2H2O}")

        Physics:

        >>> Math(r"F = G \frac{m_1 m_2}{r^2}")
    """
    cfg = resolve_defaults(
        "Math",
        display_mode=display_mode,
        throw_on_error=throw_on_error,
        renderer=renderer,
    )
    c_display_mode = cfg.get("display_mode", False)
    c_throw_on_error = cfg.get("throw_on_error", False)
    c_renderer = cfg.get("renderer", renderer)

    if c_renderer != "katex":
        raise ValueError(
            f"Unsupported math renderer: {c_renderer!r}. " "Currently only 'katex' is supported."
        )

    wrapped = _normalize_delimiters(latex, c_display_mode)
    user_cls = kwargs.pop("cls", "")
    base_cls = "math faststrap-math"
    if c_display_mode:
        base_cls += " faststrap-math-display"

    attrs: dict[str, Any] = {
        "cls": merge_classes(base_cls, user_cls),
        "data_fs_math_display": "true" if c_display_mode else "false",
        "data_fs_math_throw_on_error": "true" if c_throw_on_error else "false",
    }
    attrs.update(convert_attrs(kwargs))

    if c_display_mode:
        return Div(NotStr(wrapped), **attrs)
    return Span(NotStr(wrapped), **attrs)