Last Updated: November 21, 2025
Getting Started
<script src="https://unpkg.com/htmx.org@1.9.10"></script>
CDN installation (latest stable)
npm install htmx.org
NPM installation
<div hx-get="/api/data">Load</div>
Basic HTMX request example
Core AJAX Attributes
| Attribute | Description | Example |
|---|---|---|
| hx-get | Issue GET request | <div hx-get="/users">Load</div> |
| hx-post | Issue POST request | <button hx-post="/submit">Save</button> |
| hx-put | Issue PUT request | <form hx-put="/update">...</form> |
| hx-patch | Issue PATCH request | <div hx-patch="/user/1">Update</div> |
| hx-delete | Issue DELETE request | <button hx-delete="/user/1">Delete</button> |
Trigger Attributes
hx-trigger="click"
Default for buttons and links
hx-trigger="submit"
Default for forms
hx-trigger="change"
On input change (select, checkbox)
hx-trigger="keyup"
On keyboard key release
hx-trigger="every 2s"
Poll every 2 seconds
hx-trigger="load"
Trigger on element load
hx-trigger="revealed"
When element scrolls into viewport
hx-trigger="intersect once"
Infinite scroll pattern
hx-trigger="click consume"
Prevent event bubbling
hx-trigger="click delay:1s"
Delay request by 1 second
hx-trigger="keyup changed delay:500ms"
Debounced search input
hx-trigger="click throttle:1s"
Throttle to max once per second
Target & Swap Attributes
| Attribute | Description | Example |
|---|---|---|
| hx-target | Specify element to update | hx-target="#result" |
| hx-target="closest tr" | Find closest matching parent | Delete table row |
| hx-target="next .item" | Target next sibling with class | Progressive disclosure |
| hx-target="this" | Replace the element itself | Self-updating component |
| hx-swap="innerHTML" | Replace inner content (default) | Most common |
| hx-swap="outerHTML" | Replace entire element | Complete replacement |
| hx-swap="beforebegin" | Insert before element | Prepend to list |
| hx-swap="afterbegin" | Insert as first child | Add to top of container |
| hx-swap="beforeend" | Insert as last child | Append to list |
| hx-swap="afterend" | Insert after element | Add after current |
| hx-swap="delete" | Delete target element | Remove on success |
| hx-swap="none" | Don't swap, just trigger | Side effects only |
Swap Modifiers
hx-swap="innerHTML swap:1s"
Delay swap by 1 second
hx-swap="innerHTML settle:2s"
Settle animations over 2 seconds
hx-swap="innerHTML scroll:top"
Scroll to top of target
hx-swap="innerHTML scroll:bottom"
Scroll to bottom (chat messages)
hx-swap="innerHTML show:top"
Scroll target to top of viewport
hx-swap="innerHTML transition:true"
Enable View Transitions API
hx-swap="innerHTML focus-scroll:false"
Prevent scroll on focus
Request Configuration
hx-include="[name='email']"
Include additional inputs in request
hx-params="*"
Include all parameters
hx-params="name,email"
Include only specific params
hx-params="not password"
Exclude specific params
hx-vals='{"key":"value"}'
Add JSON values to request
hx-headers='{"X-API-Key":"123"}'
Add custom headers
hx-confirm="Are you sure?"
Confirmation dialog before request
hx-ext="json-enc"
Send JSON instead of form data
Indicators & Loading States
hx-indicator="#spinner"
Show spinner during request
<img class="htmx-indicator" src="spinner.gif" />
Auto-shown during requests
.htmx-request { opacity: 0.5; }
Style element during request
.htmx-swapping { opacity: 0; }
Style during swap phase
.htmx-settling { opacity: 1; }
Style during settle phase
History & Navigation
hx-push-url="true"
Push URL into browser history
hx-push-url="/new-url"
Push custom URL
hx-replace-url="true"
Replace current history entry
hx-boost="true"
Convert links/forms to AJAX (progressive enhancement)
hx-select="#content"
Select portion of response (with hx-boost)
hx-history="false"
Prevent history snapshot
Out of Band Swaps (OOB)
<div id="msg" hx-swap-oob="true">Updated!</div>
Update element anywhere on page (in response)
hx-swap-oob="afterbegin:#notifications"
OOB with specific swap strategy
hx-swap-oob="delete"
Delete element from response
<template>...</template>
Return multiple OOB swaps in template
Events & JavaScript API
| Event | When Fired | Use Case |
|---|---|---|
| htmx:configRequest | Before request sent | Modify headers, params |
| htmx:beforeRequest | Before request, after config | Final validation, cancellation |
| htmx:afterRequest | After request completes | Error handling, logging |
| htmx:beforeSwap | Before content swapped | Modify response HTML |
| htmx:afterSwap | After content swapped | Reinitialize plugins |
| htmx:afterSettle | After settle completes | Cleanup, animations done |
| htmx:load | New content added to DOM | Initialize new elements |
| htmx:responseError | HTTP error (4xx, 5xx) | Show error messages |
JavaScript API
htmx.ajax('GET', '/api', '#target')
Programmatic AJAX request
htmx.trigger(elem, 'myEvent', {detail: data})
Trigger custom event
htmx.on('htmx:afterSwap', (evt) => {})
Add global event listener
htmx.find('#myElement')
Find element (alias for querySelector)
htmx.remove(element)
Remove element from DOM
htmx.process(element)
Process new elements added to DOM
Common Patterns
| Pattern | Implementation | Use Case |
|---|---|---|
| Active Search | hx-get="/search" hx-trigger="keyup changed delay:500ms" | Live search as user types |
| Infinite Scroll | hx-get="/more" hx-trigger="revealed" hx-swap="afterend" | Load more on scroll |
| Polling | hx-get="/updates" hx-trigger="every 5s" | Auto-refresh data |
| Delete Row | hx-delete="/item/1" hx-target="closest tr" hx-swap="outerHTML swap:1s" | Remove table row smoothly |
| Edit in Place | hx-get="/edit" hx-target="this" hx-swap="outerHTML" | Inline editing |
| Modal Dialog | hx-get="/modal" hx-target="#modal-container" | Load modal content |
| Form Validation | hx-post="/validate" hx-trigger="blur" | Real-time validation |
| Lazy Load | hx-get="/content" hx-trigger="load" | Load on page load |
Extensions
hx-ext="json-enc"
JSON encoding for requests
hx-ext="morph"
Morphdom integration (smarter DOM updates)
hx-ext="ws"
WebSocket support
hx-ext="sse"
Server-Sent Events support
hx-ext="class-tools"
CSS class manipulation utilities
hx-ext="debug"
Enhanced debugging output
Server Response Headers
HX-Trigger: myEvent
Trigger client-side event after swap
HX-Redirect: /new-page
Client-side redirect
HX-Refresh: true
Force page refresh
HX-Location: /page
Client-side navigation (with history)
HX-Reswap: innerHTML
Override swap method
HX-Retarget: #other-element
Override target element
💡 Pro Tip:
HTMX works best when your server returns HTML fragments, not JSON. Use hx-boost for progressive enhancement of existing sites. Combine hx-trigger modifiers (delay, throttle, changed) for performant interactions. Always set hx-target to avoid replacing the wrong element. Use OOB swaps to update multiple parts of the page from a single request!