# Shortcodes at a glance

> Accordion, buttons, card, carousel, gallery, GitHub, icons, KaTeX, lead, Mermaid, chart, specs and tabs - the theme's shortcodes.

_Source: https://theme.docs.tbsch.de/post/2026-01-26-shortcodes/ · As of: 2026-01-26_


The theme ships with a handful of shortcodes - here they are, sorted
alphabetically. Diagrams (*Mermaid*) and math (*KaTeX*) show up here in brief
and are covered in depth in
[Diagrams and math](/post/2026-02-09-diagrams-and-math/).

## Accordion

Collapsible sections based on native `<details>` - **no JavaScript at all**.
By default only one entry is open at a time; with `single="false"` several may
be open. With `open="true"` an entry starts expanded.

```markdown
{{< accordion >}}
{{< accordion-item label="What is a shortcode?" icon="puzzle" >}}
A reusable building block written as **Markdown**.
{{< /accordion-item >}}
{{< accordion-item label="Do I need JavaScript?" open="true" >}}
No - it uses native `<details>`/`<summary>`.
{{< /accordion-item >}}
{{< /accordion >}}
```

<div class="tb-accordion"><details class="tb-accordion__item" name="tb-acc-1">
      <summary class="tb-accordion__summary"><svg aria-hidden="true"
  xmlns="http://www.w3.org/2000/svg"
 
 
  viewBox="0 0 24 24"
  fill="none"
  stroke="currentColor"
  stroke-width="2"
  stroke-linecap="round"
  stroke-linejoin="round"
 
>
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
  <path d="M4 7h3a1 1 0 0 0 1 -1v-1a2 2 0 0 1 4 0v1a1 1 0 0 0 1 1h3a1 1 0 0 1 1 1v3a1 1 0 0 0 1 1h1a2 2 0 0 1 0 4h-1a1 1 0 0 0 -1 1v3a1 1 0 0 1 -1 1h-3a1 1 0 0 1 -1 -1v-1a2 2 0 0 0 -4 0v1a1 1 0 0 1 -1 1h-3a1 1 0 0 1 -1 -1v-3a1 1 0 0 1 1 -1h1a2 2 0 0 0 0 -4h-1a1 1 0 0 1 -1 -1v-3a1 1 0 0 1 1 -1" />
</svg><span class="tb-accordion__label">What is a shortcode?</span>
        <span class="tb-accordion__chevron"><svg aria-hidden="true"
  xmlns="http://www.w3.org/2000/svg"
 
 
  viewBox="0 0 24 24"
  fill="none"
  stroke="currentColor"
  stroke-width="2"
  stroke-linecap="round"
  stroke-linejoin="round"
 
>
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
  <path d="M6 9l6 6l6 -6" />
</svg></span>
      </summary>
      <div class="tb-accordion__body">A reusable building block that you call <strong>right inside your Markdown</strong>.</div>
    </details><details class="tb-accordion__item" name="tb-acc-1" open>
      <summary class="tb-accordion__summary"><svg aria-hidden="true"
  xmlns="http://www.w3.org/2000/svg"
 
 
  viewBox="0 0 24 24"
  fill="none"
  stroke="currentColor"
  stroke-width="2"
  stroke-linecap="round"
  stroke-linejoin="round"
 
>
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
  <path d="M13 3l0 7l6 0l-8 11l0 -7l-6 0l8 -11" />
</svg><span class="tb-accordion__label">Do I need JavaScript for this?</span>
        <span class="tb-accordion__chevron"><svg aria-hidden="true"
  xmlns="http://www.w3.org/2000/svg"
 
 
  viewBox="0 0 24 24"
  fill="none"
  stroke="currentColor"
  stroke-width="2"
  stroke-linecap="round"
  stroke-linejoin="round"
 
>
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
  <path d="M6 9l6 6l6 -6" />
</svg></span>
      </summary>
      <div class="tb-accordion__body">No - the accordion uses native <code>&lt;details&gt;</code>/<code>&lt;summary&gt;</code> and works even with
JavaScript disabled.</div>
    </details><details class="tb-accordion__item" name="tb-acc-1">
      <summary class="tb-accordion__summary"><svg aria-hidden="true"
  xmlns="http://www.w3.org/2000/svg"
 
 
  viewBox="0 0 24 24"
  fill="none"
  stroke="currentColor"
  stroke-width="2"
  stroke-linecap="round"
  stroke-linejoin="round"
 
>
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
  <path d="M12 6l-8 4l8 4l8 -4l-8 -4" />
  <path d="M4 14l8 4l8 -4" />
</svg><span class="tb-accordion__label">Can more than one entry be open?</span>
        <span class="tb-accordion__chevron"><svg aria-hidden="true"
  xmlns="http://www.w3.org/2000/svg"
 
 
  viewBox="0 0 24 24"
  fill="none"
  stroke="currentColor"
  stroke-width="2"
  stroke-linecap="round"
  stroke-linejoin="round"
 
>
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
  <path d="M6 9l6 6l6 -6" />
</svg></span>
      </summary>
      <div class="tb-accordion__body">Not by default - set <code>single=&quot;false&quot;</code> to allow it.</div>
    </details></div>


## Amazon

Renders an affiliate product as a card. You only pass the affiliate reflink; the
title, description, image and price come from a build-time cache
(`data/products.yaml`), which `script/fetch-amazon-products.js` fills from the
Amazon Creators API — the site build itself never calls Amazon. The
product image loads from Amazon's CDN only after consent via *Klaro*, and the
link carries `rel="sponsored"` (which automatically shows the advertising
disclosure). The price is shown only while the cached data is fresh (< 24 h),
per Amazon's terms.

```markdown
{{< amazon "https://amzlink.to/az0sqPpjSZX54" >}}
```

<div class="tb-amazon-card"><div class="tb-amazon-card__media" data-name="consent-gate-amazon">
        <a class="tb-amazon-card__media-link" href="https://amzlink.to/az0sqPpjSZX54" target="_blank" rel="sponsored noopener noreferrer" aria-label="Midea Portasplit Cool Mobile Klimaanlage nur Kühlung">
          <img class="tb-amazon-card__img" data-name="consent-gate-amazon"
            data-src="https://m.media-amazon.com/images/I/71ZEuMSExZL._AC_UF894,1000_QL80_.jpg" alt="Midea Portasplit Cool Mobile Klimaanlage nur Kühlung" loading="lazy" decoding="async" referrerpolicy="no-referrer">
        </a>
      </div>
      <div class="tb-amazon-card__body">
        <p class="tb-amazon-card__title">Midea Portasplit Cool Mobile Klimaanlage nur Kühlung</p>
        <div class="tb-amazon-card__foot">
          <a class="tb-btn tb-btn-primary tb-btn-sm tb-amazon-card__cta" href="https://amzlink.to/az0sqPpjSZX54" target="_blank" rel="sponsored noopener noreferrer">View on Amazon<svg aria-hidden="true"
  xmlns="http://www.w3.org/2000/svg"
 
 
  viewBox="0 0 24 24"
  fill="none"
  stroke="currentColor"
  stroke-width="2"
  stroke-linecap="round"
  stroke-linejoin="round"
 
>
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
  <path d="M4 19a2 2 0 1 0 4 0a2 2 0 1 0 -4 0" />
  <path d="M15 19a2 2 0 1 0 4 0a2 2 0 1 0 -4 0" />
  <path d="M17 17h-11v-14h-2" />
  <path d="M6 5l14 1l-1 7h-13" />
</svg></a>
        </div>
      </div>
    </div>

It also works inside the card grid — drop several `amazon` shortcodes
between `card-grid` tags and they line up as equal-height cells:

```markdown
{{< card-grid cols=2 >}}
{{< amazon "https://amzlink.to/az0sqPpjSZX54" >}}
{{< amazon "https://amzlink.to/az0demo1234" >}}
{{< /card-grid >}}
```

<div class="tb-card-grid tb-card-grid--fixed" style="--tb-grid-cols:2">
<div class="tb-amazon-card"><div class="tb-amazon-card__media" data-name="consent-gate-amazon">
        <a class="tb-amazon-card__media-link" href="https://amzlink.to/az0sqPpjSZX54" target="_blank" rel="sponsored noopener noreferrer" aria-label="Midea Portasplit Cool Mobile Klimaanlage nur Kühlung">
          <img class="tb-amazon-card__img" data-name="consent-gate-amazon"
            data-src="https://m.media-amazon.com/images/I/71ZEuMSExZL._AC_UF894,1000_QL80_.jpg" alt="Midea Portasplit Cool Mobile Klimaanlage nur Kühlung" loading="lazy" decoding="async" referrerpolicy="no-referrer">
        </a>
      </div>
      <div class="tb-amazon-card__body">
        <p class="tb-amazon-card__title">Midea Portasplit Cool Mobile Klimaanlage nur Kühlung</p>
        <div class="tb-amazon-card__foot">
          <a class="tb-btn tb-btn-primary tb-btn-sm tb-amazon-card__cta" href="https://amzlink.to/az0sqPpjSZX54" target="_blank" rel="sponsored noopener noreferrer">View on Amazon<svg aria-hidden="true"
  xmlns="http://www.w3.org/2000/svg"
 
 
  viewBox="0 0 24 24"
  fill="none"
  stroke="currentColor"
  stroke-width="2"
  stroke-linecap="round"
  stroke-linejoin="round"
 
>
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
  <path d="M4 19a2 2 0 1 0 4 0a2 2 0 1 0 -4 0" />
  <path d="M15 19a2 2 0 1 0 4 0a2 2 0 1 0 -4 0" />
  <path d="M17 17h-11v-14h-2" />
  <path d="M6 5l14 1l-1 7h-13" />
</svg></a>
        </div>
      </div>
    </div>
<div class="tb-amazon-card"><div class="tb-amazon-card__media" data-name="consent-gate-amazon">
        <a class="tb-amazon-card__media-link" href="https://amzlink.to/az0demo1234" target="_blank" rel="sponsored noopener noreferrer" aria-label="Raspberry Pi 5 (8 GB RAM)">
          <img class="tb-amazon-card__img" data-name="consent-gate-amazon"
            data-src="https://m.media-amazon.com/images/I/71bK6Ij2nBL._AC_SL1500_.jpg" alt="Raspberry Pi 5 (8 GB RAM)" loading="lazy" decoding="async" referrerpolicy="no-referrer">
        </a>
      </div>
      <div class="tb-amazon-card__body">
        <p class="tb-amazon-card__title">Raspberry Pi 5 (8 GB RAM)</p><p class="tb-amazon-card__desc">Quad-Core Cortex-A76 @ 2,4 GHz, PCIe 2.0, Dual-4K-HDMI — der Einplatinenrechner für dein nächstes Homelab-Projekt.</p>
        <div class="tb-amazon-card__foot">
          <a class="tb-btn tb-btn-primary tb-btn-sm tb-amazon-card__cta" href="https://amzlink.to/az0demo1234" target="_blank" rel="sponsored noopener noreferrer">View on Amazon<svg aria-hidden="true"
  xmlns="http://www.w3.org/2000/svg"
 
 
  viewBox="0 0 24 24"
  fill="none"
  stroke="currentColor"
  stroke-width="2"
  stroke-linecap="round"
  stroke-linejoin="round"
 
>
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
  <path d="M4 19a2 2 0 1 0 4 0a2 2 0 1 0 -4 0" />
  <path d="M15 19a2 2 0 1 0 4 0a2 2 0 1 0 -4 0" />
  <path d="M17 17h-11v-14h-2" />
  <path d="M6 5l14 1l-1 7h-13" />
</svg></a>
        </div>
      </div>
    </div>
</div>


## Buttons

A button is a link styled as a push button.

```markdown
{{< button href="https://gohugo.io" target="_blank" >}}To the Hugo docs{{< /button >}}
{{< button href="https://example.com/produkt" sponsored="true" >}}Affiliate link{{< /button >}}
```

<a class="tb-btn tb-btn-primary tb-btn-sm"
  href="https://gohugo.io"
  target="_blank"
  rel="noopener noreferrer"
  >To the Hugo docs</a>

<a class="tb-btn tb-btn-primary tb-btn-sm"
  href="https://example.com/produkt"
  target="_blank"
  rel="sponsored noopener noreferrer"
  >Affiliate link<svg aria-hidden="true"
  xmlns="http://www.w3.org/2000/svg"
 
 
  viewBox="0 0 24 24"
  fill="none"
  stroke="currentColor"
  stroke-width="2"
  stroke-linecap="round"
  stroke-linejoin="round"
 
>
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
  <path d="M4 19a2 2 0 1 0 4 0a2 2 0 1 0 -4 0" />
  <path d="M15 19a2 2 0 1 0 4 0a2 2 0 1 0 -4 0" />
  <path d="M17 17h-11v-14h-2" />
  <path d="M6 5l14 1l-1 7h-13" />
</svg></a>


With `sponsored="true"` the button gets a shopping-cart icon and
`rel="sponsored"` - which **automatically** shows the advertising disclosure
at the top of the page (scroll up and see). Instead of `href` you can also
pass `pageRef="posts/01-willkommen"` for internal targets.

## Card

Embeds a post, category, series or page as a card right inside the text - in
the same look as the cards on the list pages. The type is detected
automatically; `type="article|category|series|page"` overrides it.

```markdown
{{< card "posts/01-willkommen" >}}
{{< card "series/example-series" >}}
```

<div class="tb-card-embed"><article class="tb-card tb-reveal h-entry">
  <a class="u-url" href="https://theme.docs.tbsch.de/post/2026-02-23-welcome/" hidden>Welcome to the tbsch theme</a><time class="dt-published" datetime="2026-02-23T00:00:00Z" hidden></time>
  <a class="tb-thumb-link" href="/post/2026-02-23-welcome/" aria-label="Welcome to the tbsch theme" tabindex="-1"ZgotmplZ><img class="tb-thumb u-photo" alt=""
      src="/img/hero-bg2_hu_df4c6bb8bb397046.webp"
      srcset="/img/hero-bg2_hu_a4848fa6a81d424d.webp 320w, /img/hero-bg2_hu_a6af3be557bd61f1.webp 560w, /img/hero-bg2_hu_df4c6bb8bb397046.webp 800w, /img/hero-bg2_hu_deaa8f89873fd34b.webp 1100w"
      sizes="(max-width:760px) 92vw, 380px"
      width="800" height="1734" loading="lazy" decoding="async"></a>
  <div class="tb-card-body"><h3><a class="p-name" href="/post/2026-02-23-welcome/"ZgotmplZ>Welcome to the tbsch theme</a></h3><a class="tb-cat tb-grad-text p-category" href="/categories/basics/"ZgotmplZ>Basics</a><p class="tb-summary p-summary">An overview of the tbsch theme: what it can do, how this demo is structured and where to start.</p><div class="tb-meta"><span class="tb-i tb-mono">Feb 23, 2026</span><span class="tb-i"><svg aria-hidden="true"
  xmlns="http://www.w3.org/2000/svg"
 
 
  viewBox="0 0 24 24"
  fill="none"
  stroke="currentColor"
  stroke-width="2"
  stroke-linecap="round"
  stroke-linejoin="round"
 
>
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
  <path d="M3 12a9 9 0 1 0 18 0a9 9 0 0 0 -18 0" />
  <path d="M12 7v5l3 3" />
</svg> 2 min</span></div>
  </div>
</article>
</div>
<div class="tb-card-embed"><article class="tb-series-card tb-reveal"><div class="tb-series-card__figframe"><img class="tb-series-card__fig" alt=""
      src="/img/hero-bg2_hu_8bf1d204d579e527.webp"
      srcset="/img/hero-bg2_hu_5f9ea8d6bdf83b3c.webp 360w, /img/hero-bg2_hu_8bf1d204d579e527.webp 600w, /img/hero-bg2_hu_df4c6bb8bb397046.webp 800w"
      sizes="(max-width:760px) 92vw, 420px"
      width="600" height="1300" loading="lazy" decoding="async"></div><div class="tb-series-card__body">
    <h3 class="tb-series-card__title"><a class="tb-series-card__link" href="/series/example-series/">Example Series</a></h3>
    <div class="tb-series-card__count">3 parts</div><p class="tb-series-card__desc">A three-part series showing how the theme links related posts together.</p><ul class="tb-series-card__parts"><li>
            <a href="/post/2025-12-01-example-series-part-1-the-beginning/">Part 1: Example Series, part 1: The beginning</a>
          </li><li>
            <a href="/post/2025-12-08-example-series-part-2-the-middle/">Part 2: Example Series, part 2: The middle</a>
          </li><li>
            <a href="/post/2025-12-15-example-series-part-3-the-end/">Part 3: Example Series, part 3: The end</a>
          </li></ul></div>
</article>
</div>

## Card grid

Several cards side by side, in the same grid look as the hub pages. `cols`
(optional, default `2`, at most `4`) sets the desktop column count; on narrow
viewports the grid collapses to a single column. The content should consist
of card shortcodes.

```markdown
{{< card-grid >}}
{{< card "posts/01-willkommen" >}}
{{< card "series/example-series" >}}
{{< /card-grid >}}
```

<div class="tb-card-grid tb-card-grid--fixed" style="--tb-grid-cols:2">
<div class="tb-card-embed"><article class="tb-card tb-reveal h-entry">
  <a class="u-url" href="https://theme.docs.tbsch.de/post/2026-02-23-welcome/" hidden>Welcome to the tbsch theme</a><time class="dt-published" datetime="2026-02-23T00:00:00Z" hidden></time>
  <a class="tb-thumb-link" href="/post/2026-02-23-welcome/" aria-label="Welcome to the tbsch theme" tabindex="-1"ZgotmplZ><img class="tb-thumb u-photo" alt=""
      src="/img/hero-bg2_hu_df4c6bb8bb397046.webp"
      srcset="/img/hero-bg2_hu_a4848fa6a81d424d.webp 320w, /img/hero-bg2_hu_a6af3be557bd61f1.webp 560w, /img/hero-bg2_hu_df4c6bb8bb397046.webp 800w, /img/hero-bg2_hu_deaa8f89873fd34b.webp 1100w"
      sizes="(max-width:760px) 92vw, 380px"
      width="800" height="1734" loading="lazy" decoding="async"></a>
  <div class="tb-card-body"><h3><a class="p-name" href="/post/2026-02-23-welcome/"ZgotmplZ>Welcome to the tbsch theme</a></h3><a class="tb-cat tb-grad-text p-category" href="/categories/basics/"ZgotmplZ>Basics</a><p class="tb-summary p-summary">An overview of the tbsch theme: what it can do, how this demo is structured and where to start.</p><div class="tb-meta"><span class="tb-i tb-mono">Feb 23, 2026</span><span class="tb-i"><svg aria-hidden="true"
  xmlns="http://www.w3.org/2000/svg"
 
 
  viewBox="0 0 24 24"
  fill="none"
  stroke="currentColor"
  stroke-width="2"
  stroke-linecap="round"
  stroke-linejoin="round"
 
>
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
  <path d="M3 12a9 9 0 1 0 18 0a9 9 0 0 0 -18 0" />
  <path d="M12 7v5l3 3" />
</svg> 2 min</span></div>
  </div>
</article>
</div>
<div class="tb-card-embed"><article class="tb-series-card tb-reveal"><div class="tb-series-card__figframe"><img class="tb-series-card__fig" alt=""
      src="/img/hero-bg2_hu_8bf1d204d579e527.webp"
      srcset="/img/hero-bg2_hu_5f9ea8d6bdf83b3c.webp 360w, /img/hero-bg2_hu_8bf1d204d579e527.webp 600w, /img/hero-bg2_hu_df4c6bb8bb397046.webp 800w"
      sizes="(max-width:760px) 92vw, 420px"
      width="600" height="1300" loading="lazy" decoding="async"></div><div class="tb-series-card__body">
    <h3 class="tb-series-card__title"><a class="tb-series-card__link" href="/series/example-series/">Example Series</a></h3>
    <div class="tb-series-card__count">3 parts</div><p class="tb-series-card__desc">A three-part series showing how the theme links related posts together.</p><ul class="tb-series-card__parts"><li>
            <a href="/post/2025-12-01-example-series-part-1-the-beginning/">Part 1: Example Series, part 1: The beginning</a>
          </li><li>
            <a href="/post/2025-12-08-example-series-part-2-the-middle/">Part 2: Example Series, part 2: The middle</a>
          </li><li>
            <a href="/post/2025-12-15-example-series-part-3-the-end/">Part 3: Example Series, part 3: The end</a>
          </li></ul></div>
</article>
</div>
</div>


With `cols=3`:

```markdown
{{< card-grid cols=3 >}}
{{< card "posts/02-markdown-grundlagen" >}}
{{< card "posts/03-admonitions" >}}
{{< card "posts/05-bilder-und-galerien" >}}
{{< /card-grid >}}
```

<div class="tb-card-grid tb-card-grid--fixed" style="--tb-grid-cols:3">
<div class="tb-card-embed"><article class="tb-card tb-reveal h-entry">
  <a class="u-url" href="https://theme.docs.tbsch.de/post/2026-01-12-markdown-basics-typography/" hidden>Markdown basics &amp; typography</a><time class="dt-published" datetime="2026-01-12T00:00:00Z" hidden></time>
  <a class="tb-thumb-link" href="/post/2026-01-12-markdown-basics-typography/" aria-label="Markdown basics &amp; typography" tabindex="-1"ZgotmplZ><img class="tb-thumb u-photo" alt=""
      src="/img/hero-bg2_hu_df4c6bb8bb397046.webp"
      srcset="/img/hero-bg2_hu_a4848fa6a81d424d.webp 320w, /img/hero-bg2_hu_a6af3be557bd61f1.webp 560w, /img/hero-bg2_hu_df4c6bb8bb397046.webp 800w, /img/hero-bg2_hu_deaa8f89873fd34b.webp 1100w"
      sizes="(max-width:760px) 92vw, 380px"
      width="800" height="1734" loading="lazy" decoding="async"></a>
  <div class="tb-card-body"><h3><a class="p-name" href="/post/2026-01-12-markdown-basics-typography/"ZgotmplZ>Markdown basics &amp; typography</a></h3><a class="tb-cat tb-grad-text p-category" href="/categories/basics/"ZgotmplZ>Basics</a><p class="tb-summary p-summary">Headings, lists, tables, code, footnotes, quotes - how the theme renders standard Markdown.</p><div class="tb-meta"><span class="tb-i tb-mono">Jan 12, 2026</span><span class="tb-i"><svg aria-hidden="true"
  xmlns="http://www.w3.org/2000/svg"
 
 
  viewBox="0 0 24 24"
  fill="none"
  stroke="currentColor"
  stroke-width="2"
  stroke-linecap="round"
  stroke-linejoin="round"
 
>
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
  <path d="M3 12a9 9 0 1 0 18 0a9 9 0 0 0 -18 0" />
  <path d="M12 7v5l3 3" />
</svg> 4 min</span></div>
  </div>
</article>
</div>
<div class="tb-card-embed"><article class="tb-card tb-reveal h-entry">
  <a class="u-url" href="https://theme.docs.tbsch.de/post/2026-01-19-admonitions-callout-boxes/" hidden>Admonitions - callout boxes</a><time class="dt-published" datetime="2026-01-19T00:00:00Z" hidden></time>
  <a class="tb-thumb-link" href="/post/2026-01-19-admonitions-callout-boxes/" aria-label="Admonitions - callout boxes" tabindex="-1"ZgotmplZ><img class="tb-thumb u-photo" alt=""
      src="/img/hero-bg2_hu_df4c6bb8bb397046.webp"
      srcset="/img/hero-bg2_hu_a4848fa6a81d424d.webp 320w, /img/hero-bg2_hu_a6af3be557bd61f1.webp 560w, /img/hero-bg2_hu_df4c6bb8bb397046.webp 800w, /img/hero-bg2_hu_deaa8f89873fd34b.webp 1100w"
      sizes="(max-width:760px) 92vw, 380px"
      width="800" height="1734" loading="lazy" decoding="async"></a>
  <div class="tb-card-body"><h3><a class="p-name" href="/post/2026-01-19-admonitions-callout-boxes/"ZgotmplZ>Admonitions - callout boxes</a></h3><a class="tb-cat tb-grad-text p-category" href="/categories/features/"ZgotmplZ>Features</a><p class="tb-summary p-summary">All coloured callout boxes in GitHub alert style: note, tip, warning, danger and more - collapsible too.</p><div class="tb-meta"><span class="tb-i tb-mono">Jan 19, 2026</span><span class="tb-i"><svg aria-hidden="true"
  xmlns="http://www.w3.org/2000/svg"
 
 
  viewBox="0 0 24 24"
  fill="none"
  stroke="currentColor"
  stroke-width="2"
  stroke-linecap="round"
  stroke-linejoin="round"
 
>
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
  <path d="M3 12a9 9 0 1 0 18 0a9 9 0 0 0 -18 0" />
  <path d="M12 7v5l3 3" />
</svg> 2 min</span></div>
  </div>
</article>
</div>
<div class="tb-card-embed"><article class="tb-card tb-reveal h-entry">
  <a class="u-url" href="https://theme.docs.tbsch.de/post/2026-02-02-images-and-galleries/" hidden>Images and galleries</a><time class="dt-published" datetime="2026-02-02T00:00:00Z" hidden></time>
  <a class="tb-thumb-link" href="/post/2026-02-02-images-and-galleries/" aria-label="Images and galleries" tabindex="-1"ZgotmplZ><img class="tb-thumb u-photo" alt=""
      src="/post/2026-02-02-images-and-galleries/feature_hu_da6eaaa7c7a4e453.webp"
      srcset="/post/2026-02-02-images-and-galleries/feature_hu_b4aec50709f12d0c.webp 320w, /post/2026-02-02-images-and-galleries/feature_hu_bf2297c1b35a8ade.webp 560w, /post/2026-02-02-images-and-galleries/feature_hu_da6eaaa7c7a4e453.webp 800w, /post/2026-02-02-images-and-galleries/feature_hu_c006bf10a50c417.webp 1100w"
      sizes="(max-width:760px) 92vw, 380px"
      width="800" height="800" loading="lazy" decoding="async"></a>
  <div class="tb-card-body"><h3><a class="p-name" href="/post/2026-02-02-images-and-galleries/"ZgotmplZ>Images and galleries</a></h3><a class="tb-cat tb-grad-text p-category" href="/categories/features/"ZgotmplZ>Features</a><p class="tb-summary p-summary">The image render hook (WebP, responsive, zoomable), image sizes, captions and the gallery shortcodes.</p><div class="tb-meta"><span class="tb-i tb-mono">Feb 2, 2026</span><span class="tb-i"><svg aria-hidden="true"
  xmlns="http://www.w3.org/2000/svg"
 
 
  viewBox="0 0 24 24"
  fill="none"
  stroke="currentColor"
  stroke-width="2"
  stroke-linecap="round"
  stroke-linejoin="round"
 
>
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
  <path d="M3 12a9 9 0 1 0 18 0a9 9 0 0 0 -18 0" />
  <path d="M12 7v5l3 3" />
</svg> 3 min</span></div>
  </div>
</article>
</div>
</div>


## Carousel

A horizontally swipeable carousel. Each slide can contain an **image** or
arbitrary **Markdown**. Without JavaScript it remains a strip operable via
swipe/scroll; with JS it gains arrow buttons, dots and keyboard control
(arrow keys).

By default the carousel wraps around to the first slide after the last one;
`loop="false"` turns that off (the arrows then stop at the ends). With
`auto=5` it advances automatically every 5 seconds - only with `loop`
active, paused on hover/focus (the timer then resumes where it stopped),
and it respects reduced motion. The active slide's pill fills up with the
timer. `ratio` sets the frame's aspect ratio
(default `"16 / 9"`, e.g. `ratio="21 / 9"` or `ratio="4 / 3"`).

```markdown
{{< carousel >}}
{{< carousel-slide >}}![Alp](carousel-1.webp){{< /carousel-slide >}}
{{< carousel-slide >}}
### Markdown too
Each slide takes **any** content - headings, lists, code.
{{< /carousel-slide >}}
{{< /carousel >}}
```

<div class="tb-carousel" data-tb-component="carousel" data-loop="true" role="group" aria-roledescription="Carousel" style="--tb-car-ratio:16 / 9">
  <div class="tb-carousel__track"><div class="tb-carousel__slide" role="group" aria-roledescription="Slide" aria-label="1 of 3"><a class="tb-zoom" href="/post/2026-01-26-shortcodes/carousel-1.webp" data-pswp-width="900" data-pswp-height="900" data-alt="Mountain landscape"><img alt="Mountain landscape"
      src="/post/2026-01-26-shortcodes/carousel-1_hu_f855ebd278fbb83.webp"
      srcset="/post/2026-01-26-shortcodes/carousel-1_hu_f0badc7c3df75f7f.webp 480w, /post/2026-01-26-shortcodes/carousel-1_hu_f855ebd278fbb83.webp 768w"
      sizes="(max-width:768px) 100vw, 768px"
      width="768" height="768" loading="lazy" decoding="async"></a></div><div class="tb-carousel__slide" role="group" aria-roledescription="Slide" aria-label="2 of 3"><h3 id="images-or-markdown">Images or Markdown <a class="tb-heading-anchor" href="#images-or-markdown" aria-label="Direct link to this section">#</a></h3>
<p>Each slide takes <strong>any</strong> content:</p>
<ul>
<li>Headings and body text</li>
<li>Lists</li>
<li><code>Code</code></li>
</ul></div><div class="tb-carousel__slide" role="group" aria-roledescription="Slide" aria-label="3 of 3"><a class="tb-zoom" href="/post/2026-01-26-shortcodes/carousel-2.webp" data-pswp-width="907" data-pswp-height="437" data-alt="Another view"><img alt="Another view"
      src="/post/2026-01-26-shortcodes/carousel-2_hu_ff989385fdebfc9c.webp"
      srcset="/post/2026-01-26-shortcodes/carousel-2_hu_f992853b3abce1fa.webp 480w, /post/2026-01-26-shortcodes/carousel-2_hu_ff989385fdebfc9c.webp 768w"
      sizes="(max-width:768px) 100vw, 768px"
      width="768" height="370" loading="lazy" decoding="async"></a></div></div><button class="tb-carousel__btn tb-carousel__btn--prev" type="button" aria-label="Previous slide"><svg aria-hidden="true"
  xmlns="http://www.w3.org/2000/svg"
 
 
  viewBox="0 0 24 24"
  fill="none"
  stroke="currentColor"
  stroke-width="2"
  stroke-linecap="round"
  stroke-linejoin="round"
 
>
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
  <path d="M15 6l-6 6l6 6" />
</svg></button>
  <button class="tb-carousel__btn tb-carousel__btn--next" type="button" aria-label="Next slide"><svg aria-hidden="true"
  xmlns="http://www.w3.org/2000/svg"
 
 
  viewBox="0 0 24 24"
  fill="none"
  stroke="currentColor"
  stroke-width="2"
  stroke-linecap="round"
  stroke-linejoin="round"
 
>
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
  <path d="M9 6l6 6l-6 6" />
</svg></button><div class="tb-carousel__dots" role="group" aria-label="Slides"><button class="tb-carousel__dot" type="button" aria-label="Slide 1 of 3"></button><button class="tb-carousel__dot" type="button" aria-label="Slide 2 of 3"></button><button class="tb-carousel__dot" type="button" aria-label="Slide 3 of 3"></button></div></div>


And with autoplay (`auto=5`) and text-only slides - their content is indented
so the arrows never cover it:

```markdown
{{< carousel auto=5 ratio="21 / 9" >}}
{{< carousel-slide >}}### Slide one …{{< /carousel-slide >}}
{{< carousel-slide >}}### Slide two …{{< /carousel-slide >}}
{{< carousel-slide >}}### Slide three …{{< /carousel-slide >}}
{{< /carousel >}}
```

<div class="tb-carousel" data-tb-component="carousel" data-loop="true" data-auto="5" role="group" aria-roledescription="Carousel" style="--tb-car-ratio:21 / 9">
  <div class="tb-carousel__track"><div class="tb-carousel__slide" role="group" aria-roledescription="Slide" aria-label="1 of 3"><h3 id="slide-one">Slide one <a class="tb-heading-anchor" href="#slide-one" aria-label="Direct link to this section">#</a></h3>
<p>Advances automatically every 5 seconds.</p></div><div class="tb-carousel__slide" role="group" aria-roledescription="Slide" aria-label="2 of 3"><h3 id="slide-two">Slide two <a class="tb-heading-anchor" href="#slide-two" aria-label="Direct link to this section">#</a></h3>
<p>Hover or focus pauses the autoplay.</p></div><div class="tb-carousel__slide" role="group" aria-roledescription="Slide" aria-label="3 of 3"><h3 id="slide-three">Slide three <a class="tb-heading-anchor" href="#slide-three" aria-label="Direct link to this section">#</a></h3>
<p>After the last slide it wraps around to the first (<code>loop</code>).</p></div></div><button class="tb-carousel__btn tb-carousel__btn--prev" type="button" aria-label="Previous slide"><svg aria-hidden="true"
  xmlns="http://www.w3.org/2000/svg"
 
 
  viewBox="0 0 24 24"
  fill="none"
  stroke="currentColor"
  stroke-width="2"
  stroke-linecap="round"
  stroke-linejoin="round"
 
>
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
  <path d="M15 6l-6 6l6 6" />
</svg></button>
  <button class="tb-carousel__btn tb-carousel__btn--next" type="button" aria-label="Next slide"><svg aria-hidden="true"
  xmlns="http://www.w3.org/2000/svg"
 
 
  viewBox="0 0 24 24"
  fill="none"
  stroke="currentColor"
  stroke-width="2"
  stroke-linecap="round"
  stroke-linejoin="round"
 
>
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
  <path d="M9 6l6 6l-6 6" />
</svg></button><div class="tb-carousel__dots" role="group" aria-label="Slides"><button class="tb-carousel__dot" type="button" aria-label="Slide 1 of 3"></button><button class="tb-carousel__dot" type="button" aria-label="Slide 2 of 3"></button><button class="tb-carousel__dot" type="button" aria-label="Slide 3 of 3"></button></div></div>


## Chart

A chart via self-hosted Chart.js, loaded only when the shortcode is present.
The inner content is the Chart.js configuration as **valid JSON**; axes, grid
and legend follow the theme and re-colour live when you toggle dark mode.

```markdown
{{< chart title="Monthly visitors" >}}
{ "type": "bar",
  "data": { "labels": ["Jan", "Feb", "Mar"],
            "datasets": [{ "label": "Visitors", "data": [820, 932, 1290] }] } }
{{< /chart >}}
```

<figure class="tb-chart" style="height:22rem">
  <canvas role="img" aria-label="Monthly visitors"></canvas>
  <script type="application/json">
{
  "type": "bar",
  "data": {
    "labels": ["Jan", "Feb", "Mar", "Apr", "May", "Jun"],
    "datasets": [{ "label": "Visitors", "data": [820, 932, 901, 1290, 1330, 1620] }]
  }
}
</script>
</figure>


## Gallery

The `gallery` shortcode arranges several images as masonry columns. In
**automatic mode** you simply write one image per line; `cols` (optional,
default `3`) sets the number of desktop columns, collapsing to a single
column on phones. All images of a gallery form **one** swipeable lightbox
group (*PhotoSwipe*); linked images (`[![…](…)](url)`) stay plain links and
are not part of the group.

```markdown
{{< gallery cols="2" >}}
![Living room](galerie-1.webp)
![Inverter](galerie-2.webp)
![Mini PC](galerie-3.webp)
![On the Mac](galerie-4.webp)
{{< /gallery >}}
```

<div class="tb-gallery" style="--tb-gallery-cols:2"><div class="tb-gallery-col"><a class="tb-zoom" href="/post/2026-01-26-shortcodes/galerie-1.webp" data-pswp-width="900" data-pswp-height="900" data-alt="Living room"><img alt="Living room"
      src="/post/2026-01-26-shortcodes/galerie-1_hu_f855ebd278fbb83.webp"
      srcset="/post/2026-01-26-shortcodes/galerie-1_hu_f0badc7c3df75f7f.webp 480w, /post/2026-01-26-shortcodes/galerie-1_hu_f855ebd278fbb83.webp 768w"
      sizes="(max-width:480px) 100vw, 50vw"
      width="768" height="768" loading="lazy" decoding="async"></a><a class="tb-zoom" href="/post/2026-01-26-shortcodes/galerie-2.webp" data-pswp-width="970" data-pswp-height="527" data-alt="Inverter"><img alt="Inverter"
      src="/post/2026-01-26-shortcodes/galerie-2_hu_aedb4664733ad3f4.webp"
      srcset="/post/2026-01-26-shortcodes/galerie-2_hu_11e5c2fb915aaaf8.webp 480w, /post/2026-01-26-shortcodes/galerie-2_hu_aedb4664733ad3f4.webp 768w"
      sizes="(max-width:480px) 100vw, 50vw"
      width="768" height="417" loading="lazy" decoding="async"></a></div><div class="tb-gallery-col"><a class="tb-zoom" href="/post/2026-01-26-shortcodes/galerie-3.webp" data-pswp-width="907" data-pswp-height="437" data-alt="Mini PC"><img alt="Mini PC"
      src="/post/2026-01-26-shortcodes/galerie-3_hu_ff989385fdebfc9c.webp"
      srcset="/post/2026-01-26-shortcodes/galerie-3_hu_f992853b3abce1fa.webp 480w, /post/2026-01-26-shortcodes/galerie-3_hu_ff989385fdebfc9c.webp 768w"
      sizes="(max-width:480px) 100vw, 50vw"
      width="768" height="370" loading="lazy" decoding="async"></a><a class="tb-zoom" href="/post/2026-01-26-shortcodes/galerie-4.webp" data-pswp-width="921" data-pswp-height="437" data-alt="On the Mac"><img alt="On the Mac"
      src="/post/2026-01-26-shortcodes/galerie-4_hu_a11ce7d248ba3a2b.webp"
      srcset="/post/2026-01-26-shortcodes/galerie-4_hu_d0c7f95cc89ca50a.webp 480w, /post/2026-01-26-shortcodes/galerie-4_hu_a11ce7d248ba3a2b.webp 768w"
      sizes="(max-width:480px) 100vw, 50vw"
      width="768" height="364" loading="lazy" decoding="async"></a></div></div>

Instead of the automatic split you can fill the columns **explicitly** with
nested `gallery-column` blocks - `cols` is then ignored and the number of
columns follows from the number of blocks. All the details (column logic,
captions, responsive sizes, linked images) are covered in
[Images and galleries](/post/2026-02-02-images-and-galleries/).

## GitHub

Embeds the OpenGraph preview of a repository. The external preview image only
loads after consent via the consent manager *Klaro* - the link to the project
always works.

```markdown
{{< github repo="gohugoio/hugo" >}}
```

<div class="tb-gh-card"><div class="tb-gh-og-gate" data-name="consent-gate-github"><a class="tb-gh-og-link" href="https://github.com/gohugoio/hugo" target="_blank" rel="noopener noreferrer" aria-label="gohugoio/hugo on GitHub">
        <img class="tb-gh-og" data-name="consent-gate-github"
          data-src="https://opengraph.githubassets.com/0/gohugoio/hugo"
          alt="gohugoio/hugo on GitHub" loading="lazy" decoding="async" width="1200" height="600" referrerpolicy="no-referrer">
      </a>
    </div>
    <a class="tb-gh-link" href="https://github.com/gohugoio/hugo" target="_blank" rel="noopener noreferrer">
      <svg aria-hidden="true"
  xmlns="http://www.w3.org/2000/svg"
 
 
  viewBox="0 0 24 24"
  fill="none"
  stroke="currentColor"
  stroke-width="2"
  stroke-linecap="round"
  stroke-linejoin="round"
 
>
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
  <path d="M9 19c-4.3 1.4 -4.3 -2.5 -6 -3m12 5v-3.5c0 -1 .1 -1.4 -.5 -2c2.8 -.3 5.5 -1.4 5.5 -6a4.6 4.6 0 0 0 -1.3 -3.2a4.2 4.2 0 0 0 -.1 -3.2s-1.1 -.3 -3.5 1.3a12.3 12.3 0 0 0 -6.2 0c-2.4 -1.6 -3.5 -1.3 -3.5 -1.3a4.2 4.2 0 0 0 -.1 3.2a4.6 4.6 0 0 0 -1.3 3.2c0 4.6 2.7 5.7 5.5 6c-.6 .6 -.6 1.2 -.5 2v3.5" />
</svg><span>Visit gohugoio/hugo on GitHub</span>
    </a>
  </div>

## Icons

`{{< ti name >}}` places a *Tabler* icon right in the text that scales
with the font size - e.g. <span class="tb-i-inline"><svg aria-hidden="true"
  xmlns="http://www.w3.org/2000/svg"
 
 
  viewBox="0 0 24 24"
  fill="none"
  stroke="currentColor"
  stroke-width="2"
  stroke-linecap="round"
  stroke-linejoin="round"
 
>
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
  <path d="M4 13a8 8 0 0 1 7 7a6 6 0 0 0 3 -5a9 9 0 0 0 6 -8a3 3 0 0 0 -3 -3a9 9 0 0 0 -8 6a6 6 0 0 0 -5 3" />
  <path d="M7 14a6 6 0 0 0 -3 6a6 6 0 0 0 6 -3" />
  <path d="M14 9a1 1 0 1 0 2 0a1 1 0 1 0 -2 0" />
</svg></span>
 or <span class="tb-i-inline"><svg aria-hidden="true"
  xmlns="http://www.w3.org/2000/svg"
 
 
  viewBox="0 0 24 24"
  fill="none"
  stroke="currentColor"
  stroke-width="2"
  stroke-linecap="round"
  stroke-linejoin="round"
 
>
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
  <path d="M3 14c.83 .642 2.077 1.017 3.5 1c1.423 .017 2.67 -.358 3.5 -1c.83 -.642 2.077 -1.017 3.5 -1c1.423 -.017 2.67 .358 3.5 1" />
  <path d="M8 3a2.4 2.4 0 0 0 -1 2a2.4 2.4 0 0 0 1 2" />
  <path d="M12 3a2.4 2.4 0 0 0 -1 2a2.4 2.4 0 0 0 1 2" />
  <path d="M3 10h14v5a6 6 0 0 1 -6 6h-2a6 6 0 0 1 -6 -6v-5" />
  <path d="M16.746 16.726a3 3 0 1 0 .252 -5.555" />
</svg></span>
.
Any name from the [Tabler outline set](https://tabler.io/icons) works
(deliberately *outline* only, not *filled* - the theme mounts just the stroke
set so every icon speaks the same line language).

## KaTeX

Place the marker shortcode `{{< katex >}}` on the page **once** - it loads
the (self-hosted) *KaTeX* renderer. After that you write math inline with
`$ ... $` and display with `$$ ... $$`; KaTeX loads only when the marker is
present.

```markdown
{{< katex >}}
Inline: Euler's identity $e^{i\pi} + 1 = 0$.
```


Inline: Euler's identity $e^{i\pi} + 1 = 0$, and the Gauss sum in display:

$$
\sum_{k=1}^{n} k = \frac{n(n+1)}{2}
$$

Display, matrix and multi-line formulas are shown in
[Diagrams and math](/post/2026-02-09-diagrams-and-math/).

## Lead

A highlighted introductory paragraph. The content is rendered as Markdown.

```markdown
{{< lead >}}
A **lead** paragraph sums up the post in a sentence or two.
{{< /lead >}}
```

<div class="tb-lead">A <strong>lead</strong> paragraph sums up the post in a sentence or two - set larger and
visually distinct from the body text.</div>


## Mermaid

Write a diagram as text inside a `mermaid` shortcode. The (self-hosted)
*Mermaid* loads only when the shortcode is present and automatically follows
the light or dark colour scheme (including live toggles).

```markdown
{{< mermaid >}}
graph LR
  A[Markdown] --> B[HTML]
{{< /mermaid >}}
```

<pre class="mermaid">
graph LR
  A[Markdown] --&gt; B[HTML]
</pre>


Flowcharts, sequence, class, state, Gantt and further diagram types are shown
in [Diagrams and math](/post/2026-02-09-diagrams-and-math/).

## Specs

A spec sheet lists a product's key facts as icon-labelled rows. Add `title2`
plus a `value2` per row to turn it into a side-by-side comparison of two
products.

```markdown
{{< specs title="Midea PortaSplit Cool" badge="Data sheet" >}}
{{< spec icon="snowflake" label="Cooling capacity" value="2.35 kW" >}}
{{< spec icon="tag" label="Price (RRP)" value="€899" >}}
{{< /specs >}}
```

<div class="tb-specs"><div class="tb-specs__head"><span class="tb-specs__badge">Data sheet</span><span class="tb-specs__title">Midea PortaSplit Cool</span></div><div class="tb-specs__row">
      <span class="tb-specs__label"><svg aria-hidden="true"
  xmlns="http://www.w3.org/2000/svg"
 
 
  viewBox="0 0 24 24"
  fill="none"
  stroke="currentColor"
  stroke-width="2"
  stroke-linecap="round"
  stroke-linejoin="round"
 
>
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
  <path d="M10 4l2 1l2 -1" />
  <path d="M12 2v6.5l3 1.72" />
  <path d="M17.928 6.268l.134 2.232l1.866 1.232" />
  <path d="M20.66 7l-5.629 3.25l.01 3.458" />
  <path d="M19.928 14.268l-1.866 1.232l-.134 2.232" />
  <path d="M20.66 17l-5.629 -3.25l-2.99 1.738" />
  <path d="M14 20l-2 -1l-2 1" />
  <path d="M12 22v-6.5l-3 -1.72" />
  <path d="M6.072 17.732l-.134 -2.232l-1.866 -1.232" />
  <path d="M3.34 17l5.629 -3.25l-.01 -3.458" />
  <path d="M4.072 9.732l1.866 -1.232l.134 -2.232" />
  <path d="M3.34 7l5.629 3.25l2.99 -1.738" />
</svg><span class="tb-specs__labeltext">Cooling capacity</span>
      </span>
      <span class="tb-specs__value">2.35 kW (8,000 BTU)</span></div><div class="tb-specs__row">
      <span class="tb-specs__label"><svg aria-hidden="true"
  xmlns="http://www.w3.org/2000/svg"
 
 
  viewBox="0 0 24 24"
  fill="none"
  stroke="currentColor"
  stroke-width="2"
  stroke-linecap="round"
  stroke-linejoin="round"
 
>
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
  <path d="M17 3l4 4l-14 14l-4 -4l14 -14" />
  <path d="M16 7l-1.5 -1.5" />
  <path d="M13 10l-1.5 -1.5" />
  <path d="M10 13l-1.5 -1.5" />
  <path d="M7 16l-1.5 -1.5" />
</svg><span class="tb-specs__labeltext">Rooms up to</span>
      </span>
      <span class="tb-specs__value">28 m²</span></div><div class="tb-specs__row">
      <span class="tb-specs__label"><svg aria-hidden="true"
  xmlns="http://www.w3.org/2000/svg"
 
 
  viewBox="0 0 24 24"
  fill="none"
  stroke="currentColor"
  stroke-width="2"
  stroke-linecap="round"
  stroke-linejoin="round"
 
>
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
  <path d="M15 8a5 5 0 0 1 0 8" />
  <path d="M17.7 5a9 9 0 0 1 0 14" />
  <path d="M6 15h-2a1 1 0 0 1 -1 -1v-4a1 1 0 0 1 1 -1h2l3.5 -4.5a.8 .8 0 0 1 1.5 .5v14a.8 .8 0 0 1 -1.5 .5l-3.5 -4.5" />
</svg><span class="tb-specs__labeltext">Noise (silent mode)</span>
      </span>
      <span class="tb-specs__value">38 dB(A)</span></div><div class="tb-specs__row">
      <span class="tb-specs__label"><svg aria-hidden="true"
  xmlns="http://www.w3.org/2000/svg"
 
 
  viewBox="0 0 24 24"
  fill="none"
  stroke="currentColor"
  stroke-width="2"
  stroke-linecap="round"
  stroke-linejoin="round"
 
>
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
  <path d="M6.5 7.5a1 1 0 1 0 2 0a1 1 0 1 0 -2 0" />
  <path d="M3 6v5.172a2 2 0 0 0 .586 1.414l7.71 7.71a2.41 2.41 0 0 0 3.408 0l5.592 -5.592a2.41 2.41 0 0 0 0 -3.408l-7.71 -7.71a2 2 0 0 0 -1.414 -.586h-5.172a3 3 0 0 0 -3 3" />
</svg><span class="tb-specs__labeltext">Price (RRP)</span>
      </span>
      <span class="tb-specs__value">€899</span></div></div>


Pass `title2` for a comparison of two products; `image`/`image2` add a product photo per column and `link`/`link2` a buy button:

<div class="tb-specs tb-specs--compare"><div class="tb-specs__head"><span class="tb-specs__badge">Comparison</span><span class="tb-specs__title">PortaSplit Cool</span><span class="tb-specs__title">PortaSplit</span></div><div class="tb-specs__media"><span class="tb-specs__media-spacer" aria-hidden="true"></span><img class="tb-specs__img" src="/post/2026-01-26-shortcodes/galerie-1_hu_a3eff9f5367a1d18.webp" width="400" height="400" alt="PortaSplit Cool" loading="lazy" decoding="async"><img class="tb-specs__img" src="/post/2026-01-26-shortcodes/galerie-2_hu_502a1fdb8ab252e.webp" width="400" height="217" alt="PortaSplit" loading="lazy" decoding="async"></div><div class="tb-specs__row">
      <span class="tb-specs__label"><svg aria-hidden="true"
  xmlns="http://www.w3.org/2000/svg"
 
 
  viewBox="0 0 24 24"
  fill="none"
  stroke="currentColor"
  stroke-width="2"
  stroke-linecap="round"
  stroke-linejoin="round"
 
>
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
  <path d="M10 4l2 1l2 -1" />
  <path d="M12 2v6.5l3 1.72" />
  <path d="M17.928 6.268l.134 2.232l1.866 1.232" />
  <path d="M20.66 7l-5.629 3.25l.01 3.458" />
  <path d="M19.928 14.268l-1.866 1.232l-.134 2.232" />
  <path d="M20.66 17l-5.629 -3.25l-2.99 1.738" />
  <path d="M14 20l-2 -1l-2 1" />
  <path d="M12 22v-6.5l-3 -1.72" />
  <path d="M6.072 17.732l-.134 -2.232l-1.866 -1.232" />
  <path d="M3.34 17l5.629 -3.25l-.01 -3.458" />
  <path d="M4.072 9.732l1.866 -1.232l.134 -2.232" />
  <path d="M3.34 7l5.629 3.25l2.99 -1.738" />
</svg><span class="tb-specs__labeltext">Cooling capacity</span>
      </span>
      <span class="tb-specs__value">2.35 kW (8,000 BTU)</span><span class="tb-specs__value">3.5 kW (12,000 BTU)</span></div><div class="tb-specs__row">
      <span class="tb-specs__label"><svg aria-hidden="true"
  xmlns="http://www.w3.org/2000/svg"
 
 
  viewBox="0 0 24 24"
  fill="none"
  stroke="currentColor"
  stroke-width="2"
  stroke-linecap="round"
  stroke-linejoin="round"
 
>
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
  <path d="M17 3l4 4l-14 14l-4 -4l14 -14" />
  <path d="M16 7l-1.5 -1.5" />
  <path d="M13 10l-1.5 -1.5" />
  <path d="M10 13l-1.5 -1.5" />
  <path d="M7 16l-1.5 -1.5" />
</svg><span class="tb-specs__labeltext">Rooms up to</span>
      </span>
      <span class="tb-specs__value">28 m²</span><span class="tb-specs__value">42 m²</span></div><div class="tb-specs__row">
      <span class="tb-specs__label"><svg aria-hidden="true"
  xmlns="http://www.w3.org/2000/svg"
 
 
  viewBox="0 0 24 24"
  fill="none"
  stroke="currentColor"
  stroke-width="2"
  stroke-linecap="round"
  stroke-linejoin="round"
 
>
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
  <path d="M15 8a5 5 0 0 1 0 8" />
  <path d="M17.7 5a9 9 0 0 1 0 14" />
  <path d="M6 15h-2a1 1 0 0 1 -1 -1v-4a1 1 0 0 1 1 -1h2l3.5 -4.5a.8 .8 0 0 1 1.5 .5v14a.8 .8 0 0 1 -1.5 .5l-3.5 -4.5" />
</svg><span class="tb-specs__labeltext">Noise (silent mode)</span>
      </span>
      <span class="tb-specs__value">38 dB(A)</span><span class="tb-specs__value">39 dB(A)</span></div><div class="tb-specs__row">
      <span class="tb-specs__label"><svg aria-hidden="true"
  xmlns="http://www.w3.org/2000/svg"
 
 
  viewBox="0 0 24 24"
  fill="none"
  stroke="currentColor"
  stroke-width="2"
  stroke-linecap="round"
  stroke-linejoin="round"
 
>
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
  <path d="M12 10.941c2.333 -3.308 .167 -7.823 -1 -8.941c0 3.395 -2.235 5.299 -3.667 6.706c-1.43 1.408 -2.333 3.294 -2.333 5.588c0 3.704 3.134 6.706 7 6.706c3.866 0 7 -3.002 7 -6.706c0 -1.712 -1.232 -4.403 -2.333 -5.588c-2.084 3.353 -3.257 3.353 -4.667 2.235" />
</svg><span class="tb-specs__labeltext">Heating</span>
      </span>
      <span class="tb-specs__value">No</span><span class="tb-specs__value">Yes</span></div><div class="tb-specs__row">
      <span class="tb-specs__label"><svg aria-hidden="true"
  xmlns="http://www.w3.org/2000/svg"
 
 
  viewBox="0 0 24 24"
  fill="none"
  stroke="currentColor"
  stroke-width="2"
  stroke-linecap="round"
  stroke-linejoin="round"
 
>
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
  <path d="M6.5 7.5a1 1 0 1 0 2 0a1 1 0 1 0 -2 0" />
  <path d="M3 6v5.172a2 2 0 0 0 .586 1.414l7.71 7.71a2.41 2.41 0 0 0 3.408 0l5.592 -5.592a2.41 2.41 0 0 0 0 -3.408l-7.71 -7.71a2 2 0 0 0 -1.414 -.586h-5.172a3 3 0 0 0 -3 3" />
</svg><span class="tb-specs__labeltext">Price (RRP)</span>
      </span>
      <span class="tb-specs__value">€899</span><span class="tb-specs__value">€1,199</span></div><div class="tb-specs__foot"><span class="tb-specs__foot-spacer" aria-hidden="true"></span><a class="tb-btn tb-btn-primary tb-btn-sm" href="https://example.com/cool" target="_blank" rel="sponsored noopener noreferrer">View offer<svg aria-hidden="true"
  xmlns="http://www.w3.org/2000/svg"
 
 
  viewBox="0 0 24 24"
  fill="none"
  stroke="currentColor"
  stroke-width="2"
  stroke-linecap="round"
  stroke-linejoin="round"
 
>
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
  <path d="M4 19a2 2 0 1 0 4 0a2 2 0 1 0 -4 0" />
  <path d="M15 19a2 2 0 1 0 4 0a2 2 0 1 0 -4 0" />
  <path d="M17 17h-11v-14h-2" />
  <path d="M6 5l14 1l-1 7h-13" />
</svg></a><a class="tb-btn tb-btn-primary tb-btn-sm" href="https://example.com/standard" target="_blank" rel="sponsored noopener noreferrer">View offer<svg aria-hidden="true"
  xmlns="http://www.w3.org/2000/svg"
 
 
  viewBox="0 0 24 24"
  fill="none"
  stroke="currentColor"
  stroke-width="2"
  stroke-linecap="round"
  stroke-linejoin="round"
 
>
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
  <path d="M4 19a2 2 0 1 0 4 0a2 2 0 1 0 -4 0" />
  <path d="M15 19a2 2 0 1 0 4 0a2 2 0 1 0 -4 0" />
  <path d="M17 17h-11v-14h-2" />
  <path d="M6 5l14 1l-1 7h-13" />
</svg></a></div></div>


## Tabs

Tabs group alternative content (e.g. per operating system). Tabs sharing the
same `group` synchronise site-wide: pick "macOS" in one group and all other
groups jump to "macOS" as well. `group` is only the internal sync key;
`label` sets the tablist's screen-reader-announced name (without `label` it
falls back to the localized default "Tabs" - never the `group` key itself).

```markdown
{{< tabs group="os" label="Operating system" >}}
{{< tab label="Linux" icon="brand-debian" >}}
`sudo apt install hugo`
{{< /tab >}}
{{< tab label="macOS" icon="brand-apple" >}}
`brew install hugo`
{{< /tab >}}
{{< /tabs >}}
```

<div class="tb-tab__container" data-tb-component="tabs" data-tab-group="os">
  <div class="tb-tab__nav" role="tablist" aria-label="Operating system"><button class="tb-tab__button tb-tab--active" type="button" role="tab"
        id="tabs-25-tab-0" aria-controls="tabs-25-panel-0"
        aria-selected="true" tabindex="0" data-tab-index="0">
        <svg aria-hidden="true"
  xmlns="http://www.w3.org/2000/svg"
 
 
  viewBox="0 0 24 24"
  fill="none"
  stroke="currentColor"
  stroke-width="2"
  stroke-linecap="round"
  stroke-linejoin="round"
 
>
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
  <path d="M12 17c-2.397 -.943 -4 -3.153 -4 -5.635c0 -2.19 1.039 -3.14 1.604 -3.595c2.646 -2.133 6.396 -.27 6.396 3.23c0 2.5 -2.905 2.121 -3.5 1.5c-.595 -.621 -1 -1.5 -.5 -2.5" />
  <path d="M3 12a9 9 0 1 0 18 0a9 9 0 1 0 -18 0" />
</svg>Linux
      </button><button class="tb-tab__button " type="button" role="tab"
        id="tabs-25-tab-1" aria-controls="tabs-25-panel-1"
        aria-selected="false" tabindex="-1" data-tab-index="1">
        <svg aria-hidden="true"
  xmlns="http://www.w3.org/2000/svg"
 
 
  viewBox="0 0 24 24"
  fill="none"
  stroke="currentColor"
  stroke-width="2"
  stroke-linecap="round"
  stroke-linejoin="round"
 
>
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
  <path d="M8.286 7.008c-3.216 0 -4.286 3.23 -4.286 5.92c0 3.229 2.143 8.072 4.286 8.072c1.165 -.05 1.799 -.538 3.214 -.538c1.406 0 1.607 .538 3.214 .538s4.286 -3.229 4.286 -5.381c-.03 -.011 -2.649 -.434 -2.679 -3.23c-.02 -2.335 2.589 -3.179 2.679 -3.228c-1.096 -1.606 -3.162 -2.113 -3.75 -2.153c-1.535 -.12 -3.032 1.077 -3.75 1.077c-.729 0 -2.036 -1.077 -3.214 -1.077" />
  <path d="M12 4a2 2 0 0 0 2 -2a2 2 0 0 0 -2 2" />
</svg>macOS
      </button><button class="tb-tab__button " type="button" role="tab"
        id="tabs-25-tab-2" aria-controls="tabs-25-panel-2"
        aria-selected="false" tabindex="-1" data-tab-index="2">
        <svg aria-hidden="true"
  xmlns="http://www.w3.org/2000/svg"
 
 
  viewBox="0 0 24 24"
  fill="none"
  stroke="currentColor"
  stroke-width="2"
  stroke-linecap="round"
  stroke-linejoin="round"
 
>
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
  <path d="M17.8 20l-12 -1.5c-1 -.1 -1.8 -.9 -1.8 -1.9v-9.2c0 -1 .8 -1.8 1.8 -1.9l12 -1.5c1.2 -.1 2.2 .8 2.2 1.9v12.1c0 1.2 -1.1 2.1 -2.2 1.9l0 .1" />
  <path d="M12 5l0 14" />
  <path d="M4 12l16 0" />
</svg>Windows
      </button></div>
  <div class="tb-tab__content"><div class="tb-tab__panel tb-tab--active" role="tabpanel" tabindex="0"
        id="tabs-25-panel-0" aria-labelledby="tabs-25-tab-0" data-tab-index="0"><p>Install via package manager:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt install hugo
</span></span></code></pre></div></div><div class="tb-tab__panel " role="tabpanel" tabindex="0"
        id="tabs-25-panel-1" aria-labelledby="tabs-25-tab-1" data-tab-index="1"><p>Install via Homebrew:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">brew install hugo
</span></span></code></pre></div></div><div class="tb-tab__panel " role="tabpanel" tabindex="0"
        id="tabs-25-panel-2" aria-labelledby="tabs-25-tab-2" data-tab-index="2"><p>Install via Winget:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="n">winget</span> <span class="n">install</span> <span class="n">Hugo</span><span class="p">.</span><span class="py">Hugo</span><span class="p">.</span><span class="py">Extended</span>
</span></span></code></pre></div></div></div>
</div>


With `default="macOS"` a tab other than the first is preselected; with
`md=false` a tab's content is not interpreted as Markdown.

This second group uses the same `group="os"` - switch the operating system
above and watch it follow along (the choice is remembered, too):

<div class="tb-tab__container" data-tb-component="tabs" data-tab-group="os">
  <div class="tb-tab__nav" role="tablist" aria-label="Tabs"><button class="tb-tab__button tb-tab--active" type="button" role="tab"
        id="tabs-26-tab-0" aria-controls="tabs-26-panel-0"
        aria-selected="true" tabindex="0" data-tab-index="0">
        <svg aria-hidden="true"
  xmlns="http://www.w3.org/2000/svg"
 
 
  viewBox="0 0 24 24"
  fill="none"
  stroke="currentColor"
  stroke-width="2"
  stroke-linecap="round"
  stroke-linejoin="round"
 
>
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
  <path d="M12 17c-2.397 -.943 -4 -3.153 -4 -5.635c0 -2.19 1.039 -3.14 1.604 -3.595c2.646 -2.133 6.396 -.27 6.396 3.23c0 2.5 -2.905 2.121 -3.5 1.5c-.595 -.621 -1 -1.5 -.5 -2.5" />
  <path d="M3 12a9 9 0 1 0 18 0a9 9 0 1 0 -18 0" />
</svg>Linux
      </button><button class="tb-tab__button " type="button" role="tab"
        id="tabs-26-tab-1" aria-controls="tabs-26-panel-1"
        aria-selected="false" tabindex="-1" data-tab-index="1">
        <svg aria-hidden="true"
  xmlns="http://www.w3.org/2000/svg"
 
 
  viewBox="0 0 24 24"
  fill="none"
  stroke="currentColor"
  stroke-width="2"
  stroke-linecap="round"
  stroke-linejoin="round"
 
>
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
  <path d="M8.286 7.008c-3.216 0 -4.286 3.23 -4.286 5.92c0 3.229 2.143 8.072 4.286 8.072c1.165 -.05 1.799 -.538 3.214 -.538c1.406 0 1.607 .538 3.214 .538s4.286 -3.229 4.286 -5.381c-.03 -.011 -2.649 -.434 -2.679 -3.23c-.02 -2.335 2.589 -3.179 2.679 -3.228c-1.096 -1.606 -3.162 -2.113 -3.75 -2.153c-1.535 -.12 -3.032 1.077 -3.75 1.077c-.729 0 -2.036 -1.077 -3.214 -1.077" />
  <path d="M12 4a2 2 0 0 0 2 -2a2 2 0 0 0 -2 2" />
</svg>macOS
      </button><button class="tb-tab__button " type="button" role="tab"
        id="tabs-26-tab-2" aria-controls="tabs-26-panel-2"
        aria-selected="false" tabindex="-1" data-tab-index="2">
        <svg aria-hidden="true"
  xmlns="http://www.w3.org/2000/svg"
 
 
  viewBox="0 0 24 24"
  fill="none"
  stroke="currentColor"
  stroke-width="2"
  stroke-linecap="round"
  stroke-linejoin="round"
 
>
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
  <path d="M17.8 20l-12 -1.5c-1 -.1 -1.8 -.9 -1.8 -1.9v-9.2c0 -1 .8 -1.8 1.8 -1.9l12 -1.5c1.2 -.1 2.2 .8 2.2 1.9v12.1c0 1.2 -1.1 2.1 -2.2 1.9l0 .1" />
  <path d="M12 5l0 14" />
  <path d="M4 12l16 0" />
</svg>Windows
      </button></div>
  <div class="tb-tab__content"><div class="tb-tab__panel tb-tab--active" role="tabpanel" tabindex="0"
        id="tabs-26-panel-0" aria-labelledby="tabs-26-tab-0" data-tab-index="0">Configuration file at <code>~/.config/hugo.toml</code>.</div><div class="tb-tab__panel " role="tabpanel" tabindex="0"
        id="tabs-26-panel-1" aria-labelledby="tabs-26-tab-1" data-tab-index="1">Configuration file at <code>~/Library/Application Support/hugo.toml</code>.</div><div class="tb-tab__panel " role="tabpanel" tabindex="0"
        id="tabs-26-panel-2" aria-labelledby="tabs-26-tab-2" data-tab-index="2">Configuration file at <code>%AppData%\hugo.toml</code>.</div></div>
</div>


