# 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:

```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:

```markdown
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:

```markdown
<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>
```

<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>

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

## Embedding media

For common providers like YouTube, Vimeo, and Spotify, the [embed syntax](/docs/embeds) 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:

```markdown
<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:

```markdown
<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:

```markdown
<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.

```markdown
<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](/docs/user-auth), wait for `auth.ready`:

```js
(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

- **No sanitization** — HTML renders exactly as written. This gives you full control but means you're responsible for valid markup.
- **Theme awareness** — use CSS variables instead of hardcoded colors so your HTML works across all three theme modes.
- **Code blocks are safe** — HTML inside fenced code blocks is displayed as code, not rendered.