htmx 4.0 is under construction — migration guide

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.

Useful when the response is plain text and you want to avoid any HTML injection.

<span hx-get="..." hx-swap="textContent">0</span>

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.

Uses the idiomorph algorithm.

<div hx-get="..." hx-swap="innerMorph"> ... <!-- This gets morphed --> </div>

outerMorph

Morphs entire element, preserving state and focus.

Uses the idiomorph algorithm.

<!-- This... --> <div hx-get="..." hx-swap="outerMorph"> ... </div> <!-- ...gets morphed -->

Morph exclusions:

Add attributes to your server templates to exclude elements from morphing:

  • hx-morph-skip — freeze entire element (attrs + children unchanged)
  • hx-morph-skip-children — freeze children only, attrs still update

Or configure globally via htmx.config.morphSkip and htmx.config.morphSkipChildren.

outerSync

Syncs attributes from the response’s outer element onto the target, then replaces the target’s children. The target element itself stays in the DOM — listeners and component state are preserved.

Useful when the server returns a full element (e.g. <section class="active">...</section>) and you want the target’s attributes updated without replacing the element itself.

<!-- Target keeps its listeners, gets new attrs + children --> <section id="main" hx-get="..." hx-swap="outerSync"> ... </section>

outerHTML on document.body automatically upgrades to outerSync so that body attributes (classes, data-attrs) are preserved across full-page swaps.

delete

Removes element (ignores response content).

<!-- This... --> <div hx-delete="..." hx-swap="delete"> ... </div> <!-- ...is removed -->

none

Doesn’t insert content (out-of-band swaps still work).

<div hx-get="..." hx-swap="none"> <!-- Response not inserted, but OOB swaps happen --> </div>

upsert

Updates existing elements by ID and inserts new ones.

Requires the upsert extension.

<div hx-get="..." hx-swap="upsert"> <!-- Existing elements with matching IDs are updated, new ones are inserted --> </div>

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.

Useful for showing loading states or coordinating with CSS animations.

<div hx-swap="innerHTML swap:1s"></div>

Default: 0ms

settle

Adds delay between the swap and the settle phase.

Useful for synchronizing htmx with CSS transition timing.

<div hx-swap="innerHTML settle:200ms"></div>

Default: 1ms

ignoreTitle

Prevents updating the page <title>.

By default, htmx updates the page title from <title> tags in responses.

<div hx-swap="innerHTML ignoreTitle:true"></div>

scroll

Auto-scroll to swapped content.

Useful for infinite scroll, chat messages, or focusing attention on new content.

<div hx-swap="beforeend scroll:bottom"></div>

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.

Values: top, bottom, none

<div hx-swap="innerHTML show:top"></div>

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>

target

Override swap target inline. Alternative to using hx-target attribute.

<div hx-swap="innerHTML target:#results"></div>

strip

Controls whether the outer element of the response content is removed before swapping.

<div hx-swap="innerHTML strip:true"></div>

swapEmpty

Controls whether an empty response body still performs the main swap (which clears the target). swapEmpty:false skips the main swap; swapEmpty:true (or a bare swapEmpty) forces it.

<!-- Skip the main swap when the response is empty --> <div hx-swap="innerHTML swapEmpty:false"></div> <!-- Force the main swap even when the response is empty --> <div hx-swap="innerHTML swapEmpty:true"></div>

Defaults to htmx.config.defaultSwapEmpty.

Caveats

  • outerHTML on document.body automatically upgrades to outerSync to preserve body attributes (classes, data-attrs). Use outerSync explicitly if you want this behaviour on other elements.