htmx 2.0 - Achieving Simple Interactive Web

2025.12.11

What is htmx

htmx is a library that enables AJAX requests, CSS transitions, WebSockets, and more using only HTML attributes. You can build interactive web applications without writing JavaScript.

New Features in htmx 2.0

Size Reduction

htmx 1.x: 14KB (gzip)
htmx 2.0: 10KB (gzip)

New Attributes

<!-- hx-disabled-elt: Disable element during request -->
<button hx-post="/api/submit"
        hx-disabled-elt="this">
  Submit
</button>

<!-- hx-on: More concise event handlers -->
<div hx-on:htmx:after-request="alert('Complete!')">
  ...
</div>

<!-- hx-inherit: Control inheritance -->
<div hx-boost="true">
  <a href="/page" hx-inherit="false">
    Disable boost
  </a>
</div>

Basic Usage

AJAX Requests

<!-- GET request -->
<button hx-get="/api/users" hx-target="#user-list">
  Get User List
</button>
<div id="user-list"></div>

<!-- POST request -->
<form hx-post="/api/users" hx-target="#result">
  <input name="name" placeholder="Name">
  <input name="email" placeholder="Email">
  <button type="submit">Register</button>
</form>
<div id="result"></div>

Trigger Customization

<!-- Search on input (with debounce) -->
<input type="search"
       name="q"
       hx-get="/search"
       hx-trigger="input changed delay:300ms"
       hx-target="#search-results">

<!-- Load more on scroll -->
<div hx-get="/api/posts?page=2"
     hx-trigger="revealed"
     hx-swap="afterend">
  Loading...
</div>

Swap Strategies

<!-- Replace inner content (default) -->
<div hx-get="/content" hx-swap="innerHTML">

<!-- Replace entire element -->
<div hx-get="/content" hx-swap="outerHTML">

<!-- Append to end -->
<div hx-get="/content" hx-swap="beforeend">

<!-- With transition -->
<div hx-get="/content" hx-swap="innerHTML transition:true">

Server-Side Integration

Express Example

app.get('/api/users', (req, res) => {
  const users = getUsers();

  // Return HTML directly
  res.send(`
    <ul>
      ${users.map(u => `<li>${u.name}</li>`).join('')}
    </ul>
  `);
});

// Fire event via HX-Trigger header
app.post('/api/users', (req, res) => {
  const user = createUser(req.body);
  res.setHeader('HX-Trigger', 'userCreated');
  res.send(`<p>Created user ${user.name}</p>`);
});

Go (Echo) Example

e.POST("/api/todos", func(c echo.Context) error {
    todo := createTodo(c.FormValue("title"))

    c.Response().Header().Set("HX-Trigger", "todoAdded")
    return c.HTML(200, fmt.Sprintf(
        `<li>%s</li>`, todo.Title,
    ))
})

Extensions

WebSocket

<script src="https://unpkg.com/htmx.org/dist/ext/ws.js"></script>

<div hx-ext="ws" ws-connect="/chat">
  <div id="messages"></div>
  <form ws-send>
    <input name="message">
    <button>Send</button>
  </form>
</div>

Server-Sent Events

<script src="https://unpkg.com/htmx.org/dist/ext/sse.js"></script>

<div hx-ext="sse" sse-connect="/events">
  <div sse-swap="message">
    Waiting for events...
  </div>
</div>

View Transitions API Support

<meta name="htmx-config" content='{"globalViewTransitions": true}'>

<style>
  ::view-transition-old(root),
  ::view-transition-new(root) {
    animation-duration: 0.3s;
  }
</style>

When to Use htmx

Good for:
- Server-side rendering focused apps
- Simple interactions
- Progressive enhancement
- Minimizing JavaScript

Not ideal for:
- Complex client state management
- Offline support needed
- Rich UI components

Summary

htmx 2.0 is a lightweight library that can build interactive web applications using only HTML extensions. It pairs well with server-side rendering and can serve as an alternative to complex JavaScript frameworks for simpler applications.

← Back to list