HTMX on a Static Site

Every example on this page actually works — no backend, no API, no fake endpoints. Just HTMX loading pre-built HTML fragments from the /fragments/ directory.


1. Click to Load Content

The simplest HTMX pattern: click a link, load a static HTML file, swap it in.

Click the button above...

How it works: The button has hx-get="/fragments/greeting.html" — HTMX fetches that static file and swaps its HTML into #load-result. That's it.


2. Tabbed Content

Each tab loads a different static HTML fragment. No JavaScript tab library needed.

Click a tab to load content...

How it works: Each tab button has a different hx-get pointing to a static fragment file. They all target the same #tab-content container.


3. Click-to-Reveal Details

Expand sections on demand without loading everything upfront.

How it works: Each heading is a button with hx-get that loads a fragment into the panel below it. Content is only fetched when the user clicks.


4. Boosted Navigation

Add hx-boost="true" to links and HTMX converts them to AJAX requests that swap the body — instant, SPA-like navigation with zero JavaScript.

How it works: The hx-boost="true" on the <nav> container applies to all links inside it. Clicking any link fetches the page via AJAX and swaps the body — no full page reload, back button still works.


5. Lazy Loading (Scroll to Reveal)

This content loads automatically when you scroll it into view:

⏳ Loading when visible...

How it works: hx-trigger="revealed" fires the GET request when the element enters the viewport. Perfect for below-the-fold content.


6. Load More Pattern

Click to append additional content below existing content.

📄 Initial Content

This was rendered at build time. Click below to load more.

How it works: hx-swap="beforeend" appends the loaded fragment after existing children instead of replacing them.


7. Inline Element Swap

Replace a single element inline within text.

The current status is: unknown

How it works: hx-swap="outerHTML" replaces the entire target element (not just its children), useful for swapping badges, status indicators, or inline widgets.


How This Works — No Backend Required

The key insight: HTMX doesn't care if the response comes from a server or a static file. It just makes an HTTP GET, gets HTML back, and swaps it in.

static/
  fragments/
    greeting.html       <- loaded by "Click to Load"
    tab-overview.html   <- loaded by "Overview" tab
    tab-attributes.html <- loaded by "Attributes" tab
    tab-examples.html   <- loaded by "Examples" tab
    detail-htmx.html    <- loaded by accordion
    detail-static.html  <- loaded by accordion
    lazy-content.html   <- loaded on scroll
    more-content.html   <- loaded by "Load More"

At build time, generate your fragment files. At runtime, HTMX loads them on demand. That's the entire architecture.

The Pattern

<!-- Any element can trigger a load -->
<button hx-get="/fragments/content.html"
        hx-target="#result"
        hx-swap="innerHTML">
  Load Content
</button>

<!-- Target container for swapped content -->
<div id="result"></div>

Useful hx-swap Values

Value Behavior
innerHTML Replace children of target
outerHTML Replace the entire target element
beforeend Append after last child (load more)
afterbegin Insert before first child
beforebegin Insert before the target
afterend Insert after the target

Useful hx-trigger Values

Value Behavior
click On click (default for buttons)
revealed When element scrolls into view
load Immediately when element loads
every 5s Polling interval (needs a server)