Targets and swaps
Insert before or after existing content
Append, prepend, or place a returned fragment next to the target without rerendering the entire list.
Adjacent swaps use the same positions as insertAdjacentHTML. They let you insert a fragment without rerendering the whole list.
beforebegin: before the target itselfafterbegin: inside the target, before its first childbeforeend: inside the target, after its last childafterend: after the target itself
To append a newly created task:
<form action="/tasks" method="post"
hx-post="/tasks"
hx-target="#task-list"
hx-swap="beforeend">
...
</form>
<ul id="task-list"></ul>
The server returns one valid <li>. The list remains and the new row is inserted at its end. Existing rows keep their scroll position and any local state, which is nicer than replacing the whole <ul> for a single addition.
Appending is correct only when the new row is the complete change. If creation also changes sorting, a total, pagination, or an empty-state message, returning the whole list region is simpler and less prone to stale UI. I start with beforeend for quick prototypes, then switch to a full list refresh when the screen gains totals or sort order.
Also consider concurrent requests. Two responses may arrive in a different order than they were sent. If order matters, synchronize the requests with hx-sync or let the server return the complete authoritative ordering. Appending two rows that should be sorted alphabetically is a common place this shows up.
afterbegin is useful when the newest item should appear at the top of a feed. The server still returns one complete row or card. Only the insertion point changes.
Try this on your own project: create two tasks quickly and confirm the list order matches what your server intended.
Lesson completed