HTMX hx-swap

Once HTMX has a response from the server and knows which element to target, it needs to know how to insert the response. The hx-swap attribute controls exactly that. Different swap strategies produce very different visual results, and choosing the right one makes your page feel natural and intuitive to users.

The Default Swap

If you omit hx-swap, HTMX uses innerHTML by default. The response replaces the inner content of the target element while keeping the target element itself in place.

All Swap Strategies

ValueWhat It Does
innerHTMLReplaces the content inside the target (default)
outerHTMLReplaces the entire target element, including the element tag itself
beforebeginInserts before the target element (as a sibling before it)
afterbeginInserts at the very start of the target's content (prepend)
beforeendInserts at the very end of the target's content (append)
afterendInserts after the target element (as a sibling after it)
deleteDeletes the target element regardless of the response
noneDoes nothing with the response (useful for side effects only)

Visual Diagram of Each Strategy

Assume the server always returns: <p>NEW</p>

  TARGET before swap:
  ┌──────────────────────┐
  │ <div id="box">       │
  │   <p>OLD</p>         │
  │ </div>               │
  └──────────────────────┘

  innerHTML:
  ┌──────────────────────┐
  │ <div id="box">       │
  │   <p>NEW</p>         │  ← OLD replaced, <div> stays
  │ </div>               │
  └──────────────────────┘

  outerHTML:
  ┌──────────────────────┐
  │ <p>NEW</p>           │  ← entire <div id="box"> replaced
  └──────────────────────┘

  beforebegin:
  ┌──────────────────────┐
  │ <p>NEW</p>           │  ← inserted before the <div>
  │ <div id="box">       │
  │   <p>OLD</p>         │
  │ </div>               │
  └──────────────────────┘

  afterbegin:
  ┌──────────────────────┐
  │ <div id="box">       │
  │   <p>NEW</p>         │  ← inserted at top of <div> content
  │   <p>OLD</p>         │
  │ </div>               │
  └──────────────────────┘

  beforeend:
  ┌──────────────────────┐
  │ <div id="box">       │
  │   <p>OLD</p>         │
  │   <p>NEW</p>         │  ← inserted at bottom of <div> content
  │ </div>               │
  └──────────────────────┘

  afterend:
  ┌──────────────────────┐
  │ <div id="box">       │
  │   <p>OLD</p>         │
  │ </div>               │
  │ <p>NEW</p>           │  ← inserted after the <div>
  └──────────────────────┘

When to Use Each Strategy

innerHTML — Replace Content

Use this when you want to update what is inside a container but keep the container element itself. Common for dashboards, tab panels, and detail boxes.

<div id="profile-details"></div>
<button hx-get="/profile/42" hx-target="#profile-details" hx-swap="innerHTML">
  View Profile
</button>

outerHTML — Replace the Whole Element

Use this when the server returns a full replacement element, including the wrapper tag. Perfect for inline edit patterns and delete operations.

<div id="task-5">
  Buy milk
  <button hx-put="/tasks/5" hx-target="#task-5" hx-swap="outerHTML">Save</button>
</div>

beforeend — Append to a List

Use this when adding new items to the bottom of a list. Each server response appends to the existing list without removing old items.

<ul id="comments">
  <li>First comment</li>
</ul>

<button hx-post="/comments" hx-target="#comments" hx-swap="beforeend">
  Add Comment
</button>

afterbegin — Prepend to a List

Use this when new items should appear at the top — like a live activity feed showing the most recent events first.

<ul id="activity-feed"></ul>

<!-- Triggered automatically by polling (covered later) -->
<div hx-get="/latest-event" hx-trigger="every 5s"
     hx-target="#activity-feed" hx-swap="afterbegin"></div>

delete — Remove Without Condition

The delete swap removes the target element from the DOM as soon as the request completes — even before HTMX reads the response body. This is useful for immediate UI feedback when you just want the element gone.

<div id="notification-5">
  You have a new message.
  <button hx-post="/dismiss/5" hx-target="#notification-5" hx-swap="delete">
    Dismiss
  </button>
</div>

none — Fire and Forget

Use none when the request has a side effect on the server (like logging a view or recording a vote) but you do not want any visible change on the page.

<div hx-post="/track-view" hx-trigger="load" hx-swap="none"></div>

Swap Timing Modifiers

You can control the timing of a swap using modifiers appended to the strategy:

hx-swap="innerHTML swap:500ms settle:300ms"
  • swap:500ms — Wait 500ms before placing the new content (lets CSS transitions run on the old content first).
  • settle:300ms — Wait 300ms after inserting before removing transition classes (lets CSS transitions run on the new content).

These modifiers work together with CSS classes that HTMX adds during requests: htmx-swapping and htmx-settling. This is how smooth fade-in and fade-out effects are built — covered in the CSS Animations topic.

Key Takeaway

The hx-swap attribute tells HTMX exactly how to insert the server's response into the target element. Use innerHTML to update content inside a container, outerHTML to replace the container entirely, beforeend to append items, afterbegin to prepend items, delete to remove an element, and none when you only need a server-side side effect. Combining the right target with the right swap strategy gives you precise, predictable control over every page update.

Leave a Comment

Your email address will not be published. Required fields are marked *