Choosing an htmx swap strategy for list and form updates
Learn how to pick the right htmx swap mode—innerHTML, outerHTML, afterbegin, beforeend, delete, or none—for updating lists or forms without a full page reload.
08 Jan 2026, 12:49 UTC

Problem and takeaway
When you need to update a part of the page—such as adding a row to a table, inserting a form field, or removing an item—without a full page reload, htmx lets you declaratively specify how the server‑returned HTML fragment should be merged into the DOM. The decision is which hx-swap value to use. The useful takeaway is: match the swap mode to the structural change you want (replace, append, prepend, delete, or no‑DOM change) while keeping the target stable and the fragment lightweight.
Decision and constraints
Decision: pick an hx-swap value that defines how htmx integrates the fragment returned from an endpoint.
Constraints to satisfy before choosing a swap:
- The endpoint must return a valid HTML fragment (no
<html>,<head>, or<body>tags). - Avoid inline scripts that rely on global state; htmx will not re‑execute them reliably.
- Keep the payload small—only the markup you need to insert or replace.
- The target element must have a stable identifier (an
idor a unique class) so htmx can locate it on every request.
Supported swap options
| Swap value | What htmx does | Typical use case |
|---|---|---|
innerHTML (default) |
Replaces the inner HTML of the target element. | Updating the whole content of a container (e.g., refreshing a list). |
outerHTML |
Replaces the target element itself with the returned fragment. | Swapping out a wrapper, such as replacing a form with a success message. |
afterbegin |
Inserts the fragment as the first child of the target. | Prepending items to a list or chat log. |
beforeend |
Appends the fragment as the last child of the target. | Adding new rows to a table or new todos to a list. |
delete |
Removes the target element’s contents (leaves the wrapper). | Clearing a list before repopulating it. |
none |
Suppresses any DOM mutation; useful for triggering other htmx attributes. | Firing a hx-trigger event without changing the UI. |
Trade‑offs
Each swap mode balances simplicity, DOM preservation, and focus management:
- innerHTML / outerHTML – simplest to reason about because the target is wholly replaced. However, any element that had focus, scroll position, or transient state inside the target is lost. Use when you truly need to discard the old content.
- afterbegin / beforeend – preserve existing children, so focus and state inside the target stay intact. They are more efficient for incremental updates because the browser only mutates the insertion point. Choose these when you are adding items to a collection.
- delete – useful when you want to keep the wrapper (e.g., a
<ul>) but clear its contents before a subsequent swap that repopulates it. It avoids removing and recreating the wrapper element. - none – lets you leverage htmx’s request/response lifecycle (e.g., to show a toast or update a status bar) without touching the DOM. It requires another attribute like
hx-swap-ooborhx-triggerto effect a change elsewhere.
Concrete implementation
The following example shows appending a new todo item to a list using beforeend. The button triggers a POST to /todos; the server returns a single <li> fragment.
Add Todo
Saving…
Server response (example):
<li class="todo">Buy milk</li>
When the button is clicked:
- htmx sends a POST to
/todos. - The server returns the fragment above.
- Because
hx-swap="beforeend"is set, htmx inserts the new<li>as the last child of the element with idtodo-list. - No full page reload occurs; focus, scroll position, and any existing
<li>elements remain unchanged.
Verification steps
To confirm the swap behaves as expected:
- Open the browser’s developer tools (F12).
- Go to the Network tab, click the button, and ensure a POST request to
/todosappears with a response containing only the<li>fragment (no<html>wrapper). - Switch to the Elements tab, locate
#todo-list, and observe that after the request finishes a new<li>element is present as the last child. - Check that the page URL in the address bar does not change and that any input focus elsewhere on the page is retained.
Limitations and practical checks
If you notice duplicated DOM structure (e.g., two <ul> elements nested), verify that the server is not returning a full page. Use the Network tab preview to confirm the response is a fragment. For complex client‑side state (e.g., form validation that depends on earlier inputs), consider pairing htmx with a lightweight state library or moving validation to the server to keep the HTML simple.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.