Skip to content

HTMX with Hyperscript — Complete Guide with Examples

DodaTech Updated 2026-06-28 5 min read

In this tutorial, you'll learn about combining HTMX with Hyperscript. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.

Hyperscript is a scripting language for HTMX that lets you add client-side behavior, event handling, and logic directly in HTML without writing JavaScript, complementing HTMX's server-driven approach.

What You'll Learn

By the end of this tutorial, you'll install Hyperscript, handle events, manipulate the DOM, set values, use control flow, and combine Hyperscript with HTMX attributes for rich client-side behavior.

Why It Matters

HTMX excels at server communication but needs a partner for client-side logic: showing/hiding elements, animating, validating forms before submit, or responding to events. Hyperscript fills this gap without a separate JavaScript file.

Real-World Use

Doda Browser's HTMX-powered settings page uses Hyperscript for client-side validation before form submission, animated UI transitions, and coordinating complex multi-step interactions that would otherwise require custom JavaScript.

Where This Fits in Your Learning Path

flowchart LR
    A["Indicators & UX"] --> B["**Hyperscript**"]
    B --> C["HTMX Extensions"]
    C --> D["HTMX Project"]
    D --> E["Advanced HTMX"]
    style B fill:#3b82f6,stroke:#2563eb,color:#fff
    style A fill:#e2e8f0,stroke:#94a3b8
    style E fill:#e2e8f0,stroke:#94a3b8

Installing Hyperscript

Add the Hyperscript script tag after HTMX.

<script src="https://cdn.jsdelivr.net/npm/htmx.org@2.x.x/dist/htmx.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/hyperscript.org@0.x.x/dist/_hyperscript.min.js"></script>

Basic Event Handling

Use the _ (underscore) attribute for Hyperscript code.

<button _="on click toggle .highlight on #content">
  Toggle Highlight
</button>

<div id="content">
  This div gets highlighted on click
</div>

<style>.highlight { background: #ffeb3b; padding: 8px; border-radius: 4px; }</style>

Expected output: Clicking the button toggles the highlight class on the content div.

Combined HTMX and Hyperscript

Trigger HTMX requests and run Hyperscript simultaneously.

<button hx-post="/api/submit"
        hx-target="#result"
        _="on htmx:afterRequest
           if event.detail.successful
             add .success to #result
           else
             add .error to #result">
  Submit
</button>

<div id="result"></div>

<style>
  .success { border-left: 4px solid #4ecdc4; }
  .error { border-left: 4px solid #ff6b6b; }
</style>

Expected output: After the HTMX request completes, Hyperscript adds a success or error class to the result div based on the response.

Form Validation with Hyperscript

Validate form fields before HTMX submission.

<form hx-post="/api/register"
      hx-target="#form-result"
      _="on submit
         if #email.value is not *@*
           halt the default
           put 'Invalid email' into #form-result
         end
         if #name.value is empty
           halt the default
           put 'Name is required' into #form-result
         end">
  <input id="name" name="name" placeholder="Name">
  <input id="email" name="email" type="email" placeholder="Email">
  <button type="submit">Register</button>
</form>
<div id="form-result"></div>

Expected output: The form validates before submission. Invalid inputs show error messages without sending the request.

DOM Manipulation

Hyperscript can add, remove, and toggle elements.

<div _="on click
        add .active to me
        set my innerHTML to 'Clicked!'">
  Click me
</div>

<button _="on click
          put 'New Item' at end of #list
          add .item to last child of #list">
  Add Item
</button>

<ul id="list"></ul>

Expected output: Clicking the first div changes its content. Clicking the button appends items to the list.

Control Flow and Conditions

Hyperscript supports if/else, loops, and wait.

<button _="on click
          set count to 0
          repeat 5 times
            increment count
            put count into #counter
            wait 500ms
          end
          put 'Done!' into #counter">
  Start Count
</button>

<div id="counter">0</div>

Expected output: Clicking the button counts from 1 to 5 with 500ms intervals, then shows "Done!".

Common Mistakes

1. Forgetting the Hyperscript script tag

Hyperscript code silently fails if the library isn't loaded. Check the browser console for errors.

2. Using Hyperscript for complex state management

Hyperscript handles simple logic well. For complex client-side state, use Alpine.js alongside HTMX.

3. Mixing Hyperscript and JavaScript event handlers

Hyperscript syntax differs from JavaScript. Don't mix _="on click" with onclick="" on the same element.

4. Not using quotes properly in Hyperscript

String values need double quotes inside the attribute: _='on click put "hello" into #output'.

5. Creating infinite loops without wait

Hyperscript loops without wait or break can freeze the browser. Always include a termination condition.

Practice Questions

  1. What attribute does Hyperscript use? The _ (underscore) attribute on any HTML element.

  2. How do you handle a click event in Hyperscript? _="on click doSomething".

  3. How do you set an element's text content? put 'text' into #elementId.

  4. Can Hyperscript listen to HTMX events? Yes. Use on htmx:afterRequest or other HTMX events.

  5. How do you prevent default behavior in Hyperscript? Use halt the default inside an event handler.

Challenge

Build a multi-step form that uses HTMX for server validation on each step and Hyperscript for client-side navigation between steps, progress indication, and field validation.

FAQ

Can Hyperscript replace JavaScript entirely?

For simple interactions, yes. For complex logic, use JavaScript libraries. Hyperscript works best alongside HTMX for lightweight behavior.

Is Hyperscript compatible with Alpine.js?

Yes. Hyperscript and Alpine.js can coexist. Use Hyperscript for HTMX-related behavior and Alpine for reactive components.

Does Hyperscript work without HTMX?

Yes. Hyperscript is independent of HTMX, though they are commonly used together.

How do I debug Hyperscript?

Add log to your Hyperscript expressions. Check the browser console for output.

Can Hyperscript make HTTP requests?

For HTTP requests, use HTMX attributes. Hyperscript handles client-side logic and UI manipulation.


Mini Project

Build an interactive dashboard with HTMX and Hyperscript. HTMX handles data fetching and updates. Hyperscript handles tab switching, notification toasts, and animated counters.

<div _="on htmx:afterRequest from #dashboard
        if event.detail.successful
          put 'Updated at ' + new Date().toLocaleTimeString() into #update-time
          add .flash to #dashboard
          wait 500ms
          remove .flash from #dashboard
        end">
  <div id="update-time">Last updated: never</div>

  <div hx-get="/api/dashboard/data"
       hx-trigger="every 30s"
       hx-target="#dashboard"
       hx-indicator="#loader"
       id="dashboard">
    Dashboard content
  </div>

  <button hx-get="/api/dashboard/data"
          hx-target="#dashboard"
          _="on click
             add .loading to me
             wait until no .htmx-request from #dashboard
             remove .loading from me">
    <span class="htmx-indicator" id="loader">Refreshing...</span>
    <span _="on load from #dashboard put 'Refresh' into me">Refresh</span>
  </button>

  <style>
    .flash { animation: flash 0.5s ease-out; }
    @keyframes flash { 0% { background: rgba(59,130,246,0.2); } 100% { background: transparent; } }
    .loading { opacity: 0.6; pointer-events: none; }
  </style>
</div>

What's Next

Extend HTMX with extensions:

Tutorial What You'll Learn
HTMX Extensions Use community HTMX extensions for advanced features
HTMX Project Build a complete production-ready HTMX application

Related topics: event-driven programming, declarative vs imperative programming.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro