Inline HTML

Write raw HTML directly in your markdown files. sitemd passes all HTML through to the final page with no sanitization or filtering — what you write is what renders.

Inline elements

Use HTML tags inside a paragraph alongside regular markdown:

This word is <mark>highlighted</mark> and this is <kbd>Ctrl+C</kbd>.

Water is H<sub>2</sub>O. The equation is E = mc<sup>2</sup>.

Use <abbr title="Hypertext Markup Language">HTML</abbr> when markdown isn't enough.

Common inline tags: <span>, <mark>, <kbd>, <abbr>, <sub>, <sup>, <small>, <del>, <ins>.

Block elements

Block-level HTML goes on its own line with blank lines above and below:

Some markdown text above.

<div style="padding: 1rem; border-left: 3px solid var(--accent); background: var(--bg-secondary);">
  <strong>Note:</strong> This is a custom callout box using theme CSS variables.
</div>

More markdown text below.

The blank lines are important — without them, markdown won't recognize where the HTML block starts and ends.

Collapsible sections

The <details> and <summary> elements create expandable sections:

<details>
<summary>Click to expand</summary>

This content is hidden by default. You can use **markdown** inside the details block — just leave a blank line after the `<summary>` tag.

- Lists work
- So do `code blocks`
- And [links](/)

</details>
Click to expand

This content is hidden by default. You can use markdown inside the details block — just leave a blank line after the <summary> tag.

  • Lists work
  • So do code blocks
  • And links

Add the open attribute to start expanded: <details open>.

Embedding media

For common providers like YouTube, Vimeo, and Spotify, the embed syntax is simpler — just embed: URL on its own line. Use inline HTML when you need full control over iframe attributes.

Embed videos, iframes, or any external content:

<video controls width="100%">
  <source src="/theme/videos/demo.mp4" type="video/mp4">
</video>

<iframe src="https://www.youtube.com/embed/VIDEO_ID"
  width="100%" height="400" frameborder="0"
  allow="accelerometer; autoplay; clipboard-write; encrypted-media"
  allowfullscreen></iframe>

Styling with theme variables

Inline styles can reference sitemd's CSS custom properties for consistent theming across light, dark, and paper modes:

<div style="color: var(--accent); border: 1px solid var(--border); padding: 1rem; border-radius: 8px;">
  This box adapts to the current theme mode automatically.
</div>

Commonly used variables:

Variable What it is
--accent Theme accent color
--text Primary text color
--text-secondary Muted text color
--bg Page background
--bg-secondary Subtle background (cards, callouts)
--border Border color

Mixing HTML and markdown

Markdown inside block-level HTML works if you leave blank lines between the HTML tags and the markdown content:

<div class="two-column" style="display: grid; grid-template-columns: 1fr 1fr; gap: 2rem;">
<div>

**Left column** with markdown content, lists, and [links](/).

</div>
<div>

**Right column** with completely different content.

</div>
</div>

Without the blank lines, the content inside the tags is treated as raw HTML and markdown syntax won't be processed.

Scripts

Inline <script> tags work the same as any other HTML — they execute when the page renders.

<div id="counter">0</div>

<script>
(function() {
  var el = document.getElementById('counter');
  var count = 0;
  el.addEventListener('click', function() {
    count++;
    el.textContent = count;
  });
})();
</script>

SPA navigation vs. full page loads

sitemd uses SPA-style navigation for internal links — clicking a link swaps the page content without a full reload. Inline scripts in the new page are re-executed after the swap.

On a full page load (direct URL, refresh, or external link), window.__sitemdAuth exists (auth.js loads in the <head>), but auth initialization is async — session recovery and magic link callbacks may still be in progress.

To safely depend on the auth API, wait for auth.ready:

(function() {
  function init() {
    var auth = window.__sitemdAuth;
    // auth is guaranteed to be available here
  }
  if (window.__sitemdAuth) window.__sitemdAuth.ready.then(init);
  else document.addEventListener('sitemd:auth-ready', init);
})();

This pattern works in both cases — on SPA navigation auth.ready is already resolved and init() runs on the next microtick; on a full page load it waits for initialization to complete.

Notes