Basics
Installation
npm install htmx.org
How It Works
HTML-drivenIssue AJAX from HTML attributes, no JS needed
Swap contentServer returns HTML fragments, htmx swaps them in
ProgressiveEnhances standard HTML; degrades gracefully
REST-friendlyWorks with any server-side framework
Attributes
Core Request Attributes
hx-get="/url"Issue GET request to URL
hx-post="/url"Issue POST request to URL
hx-put="/url"Issue PUT request to URL
hx-patch="/url"Issue PATCH request to URL
hx-delete="/url"Issue DELETE request to URL
Behavior Attributes
hx-triggerEvent that triggers the request
hx-targetElement to swap content into
hx-swapHow to swap the response content
hx-selectSelect a subset of the response HTML
hx-valsAdd extra values to the request
hx-confirmShow confirm dialog before request
hx-disableDisable htmx processing on element
Triggers
Trigger Syntax
Feed
Trigger Modifiers
changedOnly fire if value changed
delay:NsWait N seconds before firing
throttle:NmsThrottle to once per N ms
onceTrigger only the first time
from:selectorListen on a different element
every NsPoll every N seconds
loadFire on element load
revealedFire when element scrolls into view
Targets
Target Selection
Target Keywords
thisThe element itself (default)
closest <sel>Closest ancestor matching selector
find <sel>First descendant matching selector
next <sel>Next sibling matching selector
previous <sel>Previous sibling matching selector
Swapping
Swap Strategies
innerHTMLReplace inner content (default)
outerHTMLReplace entire target element
afterbeginPrepend inside target
beforeendAppend inside target
beforebeginInsert before target
afterendInsert after target
deleteRemove target element
noneNo swap, just fire events
Swap Modifiers
Headers
Request Headers (sent by htmx)
HX-RequestAlways "true" for htmx requests
HX-TargetID of the target element
HX-TriggerID of the triggered element
HX-Trigger-NameName of the triggered element
HX-Current-URLCurrent URL of the browser
HX-PromptUser response from hx-prompt
Response Headers (sent by server)
HX-RedirectClient-side redirect to URL
HX-RefreshFull page refresh if "true"
HX-RetargetOverride hx-target with CSS selector
HX-ReswapOverride hx-swap strategy
HX-TriggerTrigger client-side events
HX-Push-UrlPush URL into browser history
Events
Lifecycle Events
htmx:configRequestBefore request; modify params/headers
htmx:beforeRequestJust before AJAX call
htmx:afterRequestAfter request completes
htmx:beforeSwapBefore content is swapped in
htmx:afterSwapAfter content is swapped in
htmx:afterSettleAfter DOM settles from swap
htmx:responseErrorServer returned error status
Listening to Events
document.body.addEventListener("htmx:afterSwap", (e) => { console.log("Swapped:", e.detail.target); }); // Cancel a request document.body.addEventListener("htmx:configRequest", (e) => { if (!confirm("Proceed?")) e.preventDefault(); });
Extensions
Using Extensions
Popular Extensions
json-encEncode request body as JSON
loading-statesManage loading state CSS classes
head-supportMerge tags from responses
preloadPreload links on mousedown/hover
sseServer-Sent Events support
wsWebSocket support
response-targetsDifferent targets for error responses
Indicators
Loading Indicator
Loading...
Indicator CSS
.htmx-indicator { display: none; } .htmx-request .htmx-indicator { display: inline; } .htmx-request.htmx-indicator { display: inline; }

htmx adds htmx-request class to element during requests

Disable During Request

hx-disabled-elt adds disabled attribute during request

Common Patterns
Active Search
#results" />
Infinite Scroll
Loading more...
Delete with Confirmation
Inline Editing
Click to edit this text