Zum Inhalt springen
tbsch Theme
Funktionen

Diagramme und Mathe

Chart.js (Charts), KaTeX (Mathe) und Mermaid (Diagramme) sind selbst gehostet und werden nur dann geladen, wenn der jeweilige Shortcode auf der Seite vorkommt - kein unnötiges JavaScript auf Seiten ohne sie. Auf der Shortcodes-Seite sind sie kurz vorgestellt; hier gehen wir in die Tiefe. Jedes Beispiel hat zwei Tabs: Beispiel zeigt das Ergebnis, Code die Quelle dazu.

Charts: das Grundprinzip #

Der chart-Shortcode rendert ein Canvas mit Chart.js. Der Inhalt ist die Konfiguration als JSON (type + data); ein optionales title setzt das Accessible-Label des Canvas. Achsen-, Raster- und Textfarben sind an die Theme-Tokens gebunden und wechseln live beim Umschalten des Dark Mode; Datenreihen ohne eigene Farbe werden aus der Akzent-Palette der Seite gefüllt.

Liniendiagramm #

{
  "type": "line",
  "data": {
    "labels": ["Mo", "Di", "Mi", "Do", "Fr", "Sa", "So"],
    "datasets": [
      { "label": "Desktop", "data": [120, 132, 101, 134, 90, 60, 70], "tension": 0.35 },
      { "label": "Mobil",   "data": [220, 182, 191, 234, 210, 150, 160], "tension": 0.35 }
    ]
  }
}

Balkendiagramm #

Zwei Datenreihen werden als gruppierte Balken dargestellt; eine Legende kommt automatisch dazu.

{
  "type": "bar",
  "data": {
    "labels": ["Q1", "Q2", "Q3", "Q4"],
    "datasets": [
      { "label": "2025", "data": [42, 55, 48, 61] },
      { "label": "2026", "data": [51, 63, 59, 74] }
    ]
  }
}

Ringdiagramm #

Für eine einzelne Reihe von Anteilen gibst du der Datenreihe ein explizites backgroundColor-Array, damit jedes Segment eine eigene Farbe bekommt.

{
  "type": "doughnut",
  "data": {
    "labels": ["Organisch", "Direkt", "Social", "Verweise"],
    "datasets": [
      { "data": [58, 22, 12, 8], "backgroundColor": ["#ff5d8f", "#f59e0b", "#8b5cf6", "#12a594"] }
    ]
  }
}

Netzdiagramm #

{
  "type": "radar",
  "data": {
    "labels": ["Performance", "Barrierefreiheit", "Best Practices", "SEO", "PWA"],
    "datasets": [
      { "label": "Vorher",  "data": [72, 88, 80, 90, 40] },
      { "label": "Nachher", "data": [98, 100, 95, 100, 80] }
    ]
  }
}

KaTeX: das Grundprinzip #

Setz einmal den Marker-Shortcode {{< katex >}} auf die Seite - er lädt den KaTeX-Renderer. Die eigentliche Mathematik schreibst du danach ganz normal im Fließtext mit $ ... $ (inline) bzw. $$ ... $$ (abgesetzt); ein Marker genügt für die ganze Seite.

Inline: $E = mc^2$ steht mitten im Satz, ohne die Zeilenhöhe zu sprengen. Abgesetzt landet die Formel zentriert in eigener Zeile:

$$ \int_{-\infty}^{\infty} e^{-x^2}\,dx = \sqrt{\pi} $$
Inline: $E = mc^2$ steht mitten im Satz.

$$
\int_{-\infty}^{\infty} e^{-x^2}\,dx = \sqrt{\pi}
$$

Brüche, Wurzeln, Potenzen und Indizes #

$$ \frac{-b \pm \sqrt{b^2 - 4ac}}{2a} \qquad \sqrt[3]{x} \qquad a_{i,j}^{2} $$
$$
\frac{-b \pm \sqrt{b^2 - 4ac}}{2a}
\qquad
\sqrt[3]{x}
\qquad
a_{i,j}^{2}
$$

Summen, Produkte, Grenzwerte #

$$ \sum_{k=1}^{n} k = \frac{n(n+1)}{2} \qquad \prod_{i=1}^{n} i = n! \qquad \lim_{x \to 0} \frac{\sin x}{x} = 1 $$
$$
\sum_{k=1}^{n} k = \frac{n(n+1)}{2}
\qquad
\prod_{i=1}^{n} i = n!
\qquad
\lim_{x \to 0} \frac{\sin x}{x} = 1
$$

Griechische Buchstaben und Operatoren #

$$ \alpha,\ \beta,\ \gamma,\ \Delta,\ \Omega \qquad \nabla \cdot \vec{E} = \frac{\rho}{\varepsilon_0} \qquad x \in \mathbb{R},\ A \subseteq B $$
$$
\alpha,\ \beta,\ \gamma,\ \Delta,\ \Omega \qquad
\nabla \cdot \vec{E} = \frac{\rho}{\varepsilon_0} \qquad
x \in \mathbb{R},\ A \subseteq B
$$

Matrizen #

$$ \begin{pmatrix} a & b \\ c & d \end{pmatrix} \begin{pmatrix} x \\ y \end{pmatrix} = \begin{pmatrix} ax + by \\ cx + dy \end{pmatrix} $$
$$
\begin{pmatrix} a & b \\ c & d \end{pmatrix}
\begin{pmatrix} x \\ y \end{pmatrix} =
\begin{pmatrix} ax + by \\ cx + dy \end{pmatrix}
$$

Mehrzeilig ausgerichtet und Fallunterscheidungen #

Mit aligned richtest du an & aus, mit cases setzt du Fallunterscheidungen:

$$ \begin{aligned} f(x) &= (x+1)^2 \\ &= x^2 + 2x + 1 \end{aligned} \qquad |x| = \begin{cases} x, & \text{falls } x \ge 0 \\ -x, & \text{sonst} \end{cases} $$
$$
\begin{aligned}
  f(x) &= (x+1)^2 \\
       &= x^2 + 2x + 1
\end{aligned}
\qquad
|x| =
\begin{cases}
  x,  & \text{falls } x \ge 0 \\
  -x, & \text{sonst}
\end{cases}
$$

Mermaid: das Grundprinzip #

Du beschreibst das Diagramm als Text zwischen {{< mermaid >}} und {{< /mermaid >}} - Mermaid rendert daraus im Browser ein SVG. Die erste Zeile bestimmt den Diagrammtyp (graph/flowchart, sequenceDiagram, classDiagram, …).

graph LR
  A[Markdown] --> B{Render-Hook}
  B --> C[WebP]
  B --> D[Lightbox]
graph LR
  A[Markdown] --> B{Render-Hook}
  B --> C[WebP]
  B --> D[Lightbox]

Flussrichtung und Knotenformen #

graph/flowchart kennt die Richtungen TD (oben→unten), LR, RL und BT. Die Klammern um den Knotentext bestimmen die Form: [eckig], (rund), ([Stadion]), {Raute}, ((Kreis)).

flowchart TD
  Start([Start]) --> Frage{Alles grün?}
  Frage -->|ja| Deploy[Deploy]
  Frage -->|nein| Fix(Fehler beheben)
  Fix --> Frage
  Deploy --> Ende((Fertig))
flowchart TD
  Start([Start]) --> Frage{Alles grün?}
  Frage -->|ja| Deploy[Deploy]
  Frage -->|nein| Fix(Fehler beheben)
  Fix --> Frage
  Deploy --> Ende((Fertig))

Sequenzdiagramm #

Für Abläufe zwischen Beteiligten - mit Aktivierungsbalken und Notizen.

sequenceDiagram
  participant B as Besucher
  participant S as Server
  B->>S: GET /post/...
  activate S
  S-->>B: HTML (vorgerendert)
  deactivate S
  Note over B: Dark Mode anwenden (kein Flash)
sequenceDiagram
  participant B as Besucher
  participant S as Server
  B->>S: GET /post/...
  activate S
  S-->>B: HTML (vorgerendert)
  deactivate S
  Note over B: Dark Mode anwenden (kein Flash)

Klassendiagramm #

classDiagram
  class Beitrag {
    +string Titel
    +Date Datum
    +render() string
  }
  class Serie {
    +string Name
  }
  Serie "1" o-- "*" Beitrag : enthält
classDiagram
  class Beitrag {
    +string Titel
    +Date Datum
    +render() string
  }
  class Serie {
    +string Name
  }
  Serie "1" o-- "*" Beitrag : enthält

Zustandsdiagramm #

stateDiagram-v2
  [*] --> Entwurf
  Entwurf --> Review: einreichen
  Review --> Entwurf: Änderungen
  Review --> Veröffentlicht: freigeben
  Veröffentlicht --> [*]
stateDiagram-v2
  [*] --> Entwurf
  Entwurf --> Review: einreichen
  Review --> Entwurf: Änderungen
  Review --> Veröffentlicht: freigeben
  Veröffentlicht --> [*]

Gantt-Diagramm #

gantt
  title Projektfahrplan
  dateFormat YYYY-MM-DD
  section Planung
    Konzept        :done,    des1, 2026-01-01, 2026-01-07
    Entwurf        :active,  des2, 2026-01-08, 5d
  section Umsetzung
    Bau            :         des3, after des2, 10d
    Test & Launch  :         des4, after des3, 4d
gantt
  title Projektfahrplan
  dateFormat YYYY-MM-DD
  section Planung
    Konzept        :done,    des1, 2026-01-01, 2026-01-07
    Entwurf        :active,  des2, 2026-01-08, 5d
  section Umsetzung
    Bau            :         des3, after des2, 10d
    Test & Launch  :         des4, after des3, 4d

Tortendiagramm #

pie showData
  title Zeit pro Aufgabe
  "Schreiben" : 45
  "Basteln"   : 35
  "Aufräumen" : 20
pie showData
  title Zeit pro Aufgabe
  "Schreiben" : 45
  "Basteln"   : 35
  "Aufräumen" : 20

ER-Diagramm #

erDiagram
  KATEGORIE ||--o{ BEITRAG : hat
  BEITRAG   }o--o{ TAG     : verschlagwortet
erDiagram
  KATEGORIE ||--o{ BEITRAG : hat
  BEITRAG   }o--o{ TAG     : verschlagwortet

Mermaid übernimmt automatisch das helle bzw. dunkle Farbschema und re-rendert live, wenn du den Dark Mode umschaltest - probier oben rechts den Umschalter aus, während ein Diagramm sichtbar ist.

Unter der Haube #

Was beide Shortcodes im Hintergrund erledigen - ganz ohne Zutun:

  • Selbst gehostet, kein CDN. Mermaid, KaTeX (inklusive Schriften) und Chart.js sind aus npm ins Theme vendort und werden von der eigenen Domain geladen - DSGVO-freundlich, keine Drittanbieter-Requests.
  • Nur bei Bedarf. Die Bibliotheken landen ausschließlich auf Seiten, die den mermaid-, katex- bzw. chart-Shortcode nutzen (.HasShortcode). Seiten ohne Diagramme, Formeln oder Charts laden kein zusätzliches JavaScript.
  • CSP-freundlich. Die Init-Skripte werden als reguläre <script src> mit Subresource-Integrity defer geladen, nicht inline - eine strenge Content Security Policy ohne unsafe-inline bleibt möglich.
  • Dark Mode live. Ein MutationObserver auf html.dark rendert die Diagramme neu und thematisiert die Charts um, sobald das Farbschema wechselt (Mermaid und Chart.js thematisieren nur zur Render-Zeit).
  • Stabile Größen. Mermaid misst Textboxen beim Rendern; das Init wartet auf document.fonts.ready, damit die Diagramme mit der geladenen Schrift vermessen werden und ihre Größe zwischen Reloads nicht springt.
  • Sicher. Mermaid läuft mit securityLevel: "strict". KaTeX rendert per Auto-Render nur die Prosa-Bereiche der Seite und lässt Code-Blöcke unangetastet - $-Zeichen in Beispielen bleiben also stehen.
Mitgeredet

Reaktionen

Noch keine Reaktionen - sei die/der Erste.

Weiterlesen

Verwandte Beiträge