The hx-swap attribute controls where the response content goes.
Defaults to innerHTML (configurable via htmx.config.defaultSwap)
Examples
<!-- Replace content in container --> <div hx-get="..." hx-swap="innerHTML"></div> <!-- Append to list and scroll down --> <div hx-get="..." hx-swap="beforeend scroll:bottom"></div> <!-- Update form with smooth transition --> <form hx-post="..." hx-swap="outerHTML transition:true"></form>
Swap Methods
innerHTML
Replaces content inside element.
<div hx-get="..." hx-swap="innerHTML"> <!-- This... --> ... <!-- ...gets replaced --> </div>
outerHTML
Replaces entire element.
<!-- This... --> <div hx-get="..." hx-swap="outerHTML"> ... </div> <!-- ...gets replaced -->
textContent
Replaces the text content of the element, without parsing the response as HTML.
<span hx-get="..." hx-swap="textContent">0</span>
Useful for plain text responses without HTML injection.
beforebegin / before
Inserts content before element.
<!-- Response goes here --> <div hx-get="..." hx-swap="beforebegin"> ... </div>
Can also use hx-swap="before"
afterbegin / prepend
Inserts content as first child.
<div hx-get="..." hx-swap="afterbegin"> <!-- Response goes here --> ... </div>
Can also use hx-swap="prepend"
beforeend / append
Inserts content as last child.
<div hx-get="..." hx-swap="beforeend"> ... <!-- Response goes here --> </div>
Can also use hx-swap="append"
afterend / after
Inserts content after element.
<div hx-get="..." hx-swap="afterend"> ... </div> <!-- Response goes here -->
Can also use hx-swap="after"
innerMorph
Morphs content inside element, preserving state and focus.
<div hx-get="..." hx-swap="innerMorph"> ... <!-- This gets morphed --> </div>
outerMorph
Morphs entire element, preserving state and focus.
<!-- This... --> <div hx-get="..." hx-swap="outerMorph"> ... </div> <!-- ...gets morphed -->
Skip morphing with:
hx-morph-skip: attributes and childrenhx-morph-skip-children: children only; attributes still morph
Global selectors: htmx.config.morphSkip / htmx.config.morphSkipChildren
outerSync
Morphs the target’s attributes, then replaces its children.
<!-- These attributes... --> <section id="main" hx-get="..." hx-swap="outerSync"> <!-- ...are morphed --> <!-- These children... --> ... <!-- ...are replaced --> </section>
The target stays in the DOM, preserving listeners and component state.
delete
Removes element (ignores response content).
<!-- This... --> <div hx-delete="..." hx-swap="delete"> ... </div> <!-- ...is removed -->
none
Doesn’t insert content.
<div hx-get="..." hx-swap="none"> <!-- Response not inserted, but OOB swaps happen --> </div>
hx-swap-oob and <hx-partial> swaps still work.
upsert
Updates existing elements by ID and inserts new ones.
<div hx-get="..." hx-swap="upsert"> <!-- Existing elements with matching IDs are updated, new ones are inserted --> </div>
Requires the hx-upsert extension.
Modifiers
Customize swap behavior with modifiers.
transition
Enables View Transitions API for smooth page transitions.
<div hx-swap="innerHTML transition:true"></div>
Enable globally: htmx.config.transitions = true
swap
Adds delay before swap.
<div hx-swap="innerHTML swap:1s"></div>
Useful for showing loading states or coordinating with CSS animations.
Default: 0ms
settle
Adds delay between the swap and the settle phase.
<div hx-swap="innerHTML settle:200ms"></div>
Useful for synchronizing htmx with CSS transition timing.
Default: 1ms
ignoreTitle
Prevents updating the page <title>.
<div hx-swap="innerHTML ignoreTitle:true"></div>
By default, htmx updates the page title from response <title> tags.
scroll
Auto-scroll to swapped content.
<div hx-swap="beforeend scroll:bottom"></div>
Useful for infinite scroll, chat messages, or focusing attention on new content.
Values: top, bottom
Target a different element:
<div hx-swap="innerHTML scroll:top scrollTarget:#other"></div>
Scroll the window:
<div hx-swap="innerHTML scroll:window:top"></div>
show
Scrolls to show the target element in viewport.
<div hx-swap="innerHTML show:top"></div>
Values: top, bottom, none
Show a different element:
<div hx-swap="innerHTML show:top showTarget:#other"></div>
Boosted forms default to show:top. Disable:
<form hx-swap="show:none"></form>
focusScroll
Controls whether restoring focus after a swap scrolls the focused element into view.
<input id="search" hx-get="/search" hx-swap="innerHTML focusScroll:true">
Default: htmx.config.defaultFocusScroll
target
Sets the swap target.
<div hx-swap="innerHTML target:#results"></div>
Alternative to the hx-target attribute.
strip
Controls whether the response’s outer element is removed.
Response:
<section><p>Hello</p></section>
Results:
<!-- strip:true --> <div id="target"><p>Hello</p></div> <!-- strip:false --> <div id="target"><section><p>Hello</p></section></div>
swapEmpty
Controls the main target when no main content remains.
The server might send:
<div id="notice" hx-swap-oob="true">Updated</div>
After htmx extracts the hx-swap-oob update, no main content remains:
(empty)
Use swapEmpty to keep the target or clear it:
<!-- Keep the main target --> <div hx-swap="innerHTML swapEmpty:false">Original</div> <!-- These are equivalent --> <div hx-swap="innerHTML swapEmpty:true">Original</div> <div hx-swap="innerHTML swapEmpty">Original</div>
Default: htmx.config.defaultSwapEmpty
Caveats
-
On
<body>,outerHTMLbehaves likeouterSync:<!-- This... --> <body hx-get="..." hx-swap="outerHTML">...</body> <!-- ...behaves like this --> <body hx-get="..." hx-swap="outerSync">...</body>This is because replacing
<body>would remove its event listeners and state.