HTMX Attributes — Complete Reference Guide
In this tutorial, you'll learn about HTMX attributes. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.
HTMX attributes extend HTML with AJAX capabilities directly in markup, enabling HTTP requests, response swapping, event triggers, and CSS transitions without writing JavaScript.
What You'll Learn
By the end of this tutorial, you'll master all core HTMX attributes: request attributes (hx-get, hx-post, etc.), target attributes (hx-target, hx-swap), trigger attributes (hx-trigger), and utility attributes (hx-indicator, hx-vals).
Why It Matters
Each HTMX attribute controls a specific aspect of the request-response cycle. Understanding them all lets you build complex interactions without JavaScript, from simple button clicks to sophisticated polling and lazy-loading patterns.
Real-World Use
Doda Browser's settings page uses a combination of HTMX attributes: hx-put for saving preferences, hx-trigger with debounce for search inputs, hx-indicator for loading states, and hx-target for updating the correct DOM region.
Where This Fits in Your Learning Path
flowchart LR
A["Getting Started"] --> B["**HTMX Attributes**"]
B --> C["Targets & Swapping"]
C --> D["Triggers & Events"]
D --> E["Advanced HTMX"]
style B fill:#3b82f6,stroke:#2563eb,color:#fff
style A fill:#e2e8f0,stroke:#94a3b8
style E fill:#e2e8f0,stroke:#94a3b8
Request Attributes
The six HTTP method attributes initiate AJAX requests.
<!-- GET: retrieve data -->
<button hx-get="/api/users">Load Users</button>
<!-- POST: create new data -->
<form hx-post="/api/users">
<input name="name">
<button type="submit">Create</button>
</form>
<!-- PUT: replace data -->
<button hx-put="/api/users/1" hx-target="#user-1">Update User</button>
<!-- PATCH: partial update -->
<button hx-patch="/api/users/1" hx-vals='{"role": "admin"}'>Make Admin</button>
<!-- DELETE: remove data -->
<button hx-delete="/api/users/1" hx-target="#user-1" hx-swap="outerHTML">Delete</button>
Expected output: Each button makes the corresponding HTTP request. DELETE removes the user from the DOM.
Target Attributes
hx-target specifies where the response HTML goes.
<!-- Target by CSS selector -->
<button hx-get="/api/time" hx-target="#clock">Update Time</button>
<div id="clock">Current time appears here</div>
<!-- Target the triggering element itself -->
<button hx-get="/api/self-update" hx-target="this">Replace Myself</button>
<!-- Target the closest ancestor -->
<div class="card">
<button hx-get="/api/card" hx-target="closest .card" hx-swap="outerHTML">
Refresh Card
</button>
</div>
Expected output: The response HTML replaces the specified target element. Using "this" replaces the button itself.
Trigger Attributes
hx-trigger controls what event initiates the request.
<!-- On click (default for buttons) -->
<button hx-get="/api/data">Click me</button>
<!-- On load (lazy load) -->
<div hx-get="/api/initial-data" hx-trigger="load">Loading...</div>
<!-- On input change with debounce -->
<input hx-get="/api/search" hx-trigger="input changed delay:300ms" hx-target="#results">
<!-- Every 5 seconds (polling) -->
<div hx-get="/api/status" hx-trigger="every 5s">Status: checking...</div>
<!-- On mouse enter -->
<span hx-get="/api/tooltip" hx-trigger="mouseenter" hx-target="#tooltip">Hover me</span>
Expected output: Each element triggers a request at different events. The search input waits 300ms after typing stops.
Swap Attributes
hx-swap controls how the response replaces the target.
<!-- Default: replace innerHTML -->
<div hx-get="/api/content" hx-swap="innerHTML">Replaced</div>
<!-- Replace the target element itself -->
<div hx-get="/api/new-card" hx-swap="outerHTML">Entirely replaced</div>
<!-- Append content -->
<button hx-get="/api/next" hx-target="#list" hx-swap="beforeend">Add Item</button>
<ul id="list"><li>Existing</li></ul>
<!-- Prepend content -->
<button hx-get="/api/new-top" hx-target="#list" hx-swap="afterbegin">Add to Top</button>
Expected output: innerHTML replaces content inside. outerHTML replaces the element itself. beforeend and afterbegin add content relative to the target.
Common Mistakes
1. Forgetting hx-target for complex interactions
Without hx-target, the response replaces the triggering element. Always set hx-target explicitly for non-trivial layouts.
2. Using wrong HTTP method attributes
Use hx-post for form submissions, hx-put for full updates, hx-patch for partial updates. Using GET for mutations violates REST conventions.
3. Not quoting attribute values containing special characters
Triggers like "input changed delay:300ms" need proper quoting. Use single quotes inside the attribute.
4. Using hx-trigger="load" on elements with heavy responses
Lazy Loading fires on page load. Too many simultaneous load triggers can overwhelm the server.
5. Mixing hx-swap values incorrectly
Using outerHTML when you meant innerHTML removes the target container. Using innerHTML when you meant outerHTML leaves the empty container.
Practice Questions
What does hx-get do? It makes an HTTP GET request to the specified URL when the element is triggered.
What is the default swap behavior? innerHTML, which replaces the content inside the target element.
How do you make a request on page load? Use hx-trigger="load" on the element.
What does hx-target="this" do? The response replaces the element that triggered the request.
How do you create a polling interval? Use hx-trigger="every 5s" for requests every 5 seconds.
Challenge
Build a dashboard widget that uses hx-get for data, hx-trigger="every 10s" for auto-refresh, hx-target for output, hx-indicator for loading, and hx-swap for smooth updates.
FAQ
{{< faq "How do I pass data with hx-vals?" "Use JSON in hx-vals: hx-vals='{"key": "value"}' or hx-vals='{"page": 2}'." >}}
Mini Project
Build a CRUD interface using only HTMX attributes. A table lists items with edit and delete buttons. A form creates new items. Each action uses the appropriate HTTP method and target attribute.
<div hx-get="/api/items" hx-trigger="load" hx-target="#items-table">
Loading items...
</div>
<table id="items-table">
<thead>
<tr><th>Name</th><th>Actions</th></tr>
</thead>
<tbody>
<!-- Items load here from the server -->
</tbody>
</table>
<form hx-post="/api/items" hx-target="#items-table" hx-swap="beforeend">
<input name="name" placeholder="Item name" required>
<button type="submit">Add Item</button>
</form>
<!-- Each row (returned from server) -->
<!-- <tr id="item-1">
<td>Sample Item</td>
<td>
<button hx-delete="/api/items/1" hx-target="#item-1" hx-swap="outerHTML">Delete</button>
<button hx-get="/api/items/1/edit" hx-target="#edit-form">Edit</button>
</td>
</tr> -->
What's Next
Dive deeper into targets:
| Tutorial | What You'll Learn |
|---|---|
| HTMX Targets | Advanced target selection with CSS selectors |
| HTMX Triggers | Advanced trigger configurations and modifiers |
Related topics: HTML attributes reference, AJAX and HTTP requests.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro