# How htmx Resolves hx-* vs data-hx-* Attributes: Implementation Details

> Discover how htmx handles hx-* vs data-hx-* attributes. Learn about its resolution helper and how it prioritizes native form attributes for seamless implementation.

- Repository: [Big Sky Software/htmx](https://github.com/bigskysoftware/htmx)
- Tags: internals
- Published: 2026-08-30

---

**htmx treats both `hx-*` and `data-hx-*` attribute prefixes as interchangeable by using a centralized resolution helper that checks for the native form first, then falls back to the data- attribute form.**

The bigskysoftware/htmx library accepts both `hx-trigger` and `data-hx-trigger` syntaxes to accommodate varying HTML validation requirements and developer preferences. According to the source code in [`src/htmx.js`](https://github.com/bigskysoftware/htmx/blob/main/src/htmx.js), htmx normalizes these dual prefixes through a single internal helper function, ensuring consistent behavior regardless of which syntax you choose.

## The Attribute Resolution Algorithm in src/htmx.js

At the core of htmx's attribute handling lies a resolution routine implemented in **[`src/htmx.js`](https://github.com/bigskysoftware/htmx/blob/main/src/htmx.js)** (around line 350). The **`resolveAttribute(elt, name)`** function constructs a composite CSS selector that matches both attribute forms, then traverses the DOM to locate the nearest applicable element.

The function builds the selector pattern:

```javascript
'[hx-' + name + '], [data-hx-' + name + ']'

```

This selector is passed to `element.closest()`, enabling htmx to check both the element itself and its ancestors for attribute definitions. The resolution logic explicitly prioritizes the shorter syntax:

```javascript
// Simplified representation from src/htmx.js (lines 350–360)
function resolveAttribute(elt, name) {
  var selector = '[hx-' + name + '], [data-hx-' + name + ']';
  var target = elt.closest(selector);
  // Prefer hx-* over data-hx-*
  return target && (target.getAttribute('hx-' + name) || 
                    target.getAttribute('data-hx-' + name));
}

```

Because every htmx feature uses this single resolution point, **triggers**, **swaps**, **targets**, and **extensions** automatically work with either syntax without additional branching code.

## Priority Order and Precedence Rules

When both attributes exist on the same element, htmx follows a strict precedence hierarchy. The resolution helper evaluates **`target.getAttribute('hx-' + name)`** before falling back to **`target.getAttribute('data-hx-' + name)`**, meaning the bare `hx-*` form always takes priority.

This behavior ensures backward compatibility and predictable overrides:

```html
<div hx-get="/api/primary" data-hx-get="/api/backup">
  <button>Click triggers /api/primary</button>
</div>

```

In this scenario, htmx ignores the `data-hx-get` value entirely because the `hx-get` attribute is present and checked first.

## Why htmx Supports Both Syntaxes

**HTML5 Validation Compliance**: Environments with strict validation policies or legacy content management systems often reject custom attributes lacking the `data-` prefix. The `data-hx-*` form guarantees standard HTML5 compliance.

**Developer Ergonomics**: Teams preferring concise markup can use the shorter `hx-*` syntax without sacrificing functionality. Both forms resolve to identical internal values through the centralized `resolveAttribute` routine.

## Practical Implementation Examples

You can safely intermix both syntaxes within the same project or DOM hierarchy:

```html
<!-- Standard syntax -->
<button hx-get="/users" hx-trigger="click">Load Users</button>

<!-- Data attribute syntax for strict validators -->
<button data-hx-get="/users" data-hx-trigger="click">Load Users</button>

<!-- Parent uses standard, child uses data- syntax -->
<div hx-target="#result">
  <button data-hx-get="/data">Fetch</button>
</div>

```

The `closest()` traversal means attributes inherit down the tree regardless of which prefix syntax you employ at each level.

## Key Source Files

- **[`src/htmx.js`](https://github.com/bigskysoftware/htmx/blob/main/src/htmx.js)**: Contains the `resolveAttribute` function (lines 350–360) and the selector construction logic `'[hx-' + name + '], [data-hx-' + name + ']'`.
- **[`dist/htmx.js`](https://github.com/bigskysoftware/htmx/blob/main/dist/htmx.js)**: Production build containing the same resolution logic for runtime use.
- **`test/attributes/`**: Test suites confirming identical behavior between `hx-*` and `data-hx-*` variants across all attribute types.

## Summary

- **Dual syntax support**: htmx accepts both `hx-*` and `data-hx-*` prefixes through a unified resolution mechanism in [`src/htmx.js`](https://github.com/bigskysoftware/htmx/blob/main/src/htmx.js).
- **Priority hierarchy**: The bare `hx-*` attribute always takes precedence over `data-hx-*` when both are present on the same element.
- **DOM traversal**: The `resolveAttribute` function uses `element.closest()` to check ancestors, supporting inherited configurations with either syntax.
- **Zero functional difference**: Both forms produce identical behavior; the choice depends solely on your HTML validation requirements.

## Frequently Asked Questions

### Can I mix hx-* and data-hx-* attributes on the same element?

Yes, though `hx-*` always wins. The `resolveAttribute` function explicitly checks `getAttribute('hx-' + name)` before falling back to the data-prefixed version, so the shorter syntax acts as an override.

### Which syntax takes priority if both are present?

The `hx-*` form takes priority. As implemented in [`src/htmx.js`](https://github.com/bigskysoftware/htmx/blob/main/src/htmx.js), the resolution helper returns the value of the native attribute immediately if found, only consulting `data-hx-*` if the primary attribute is absent.

### Is the data-hx-* syntax required for HTML validation?

Only if you operate under strict HTML5 validators that reject custom attributes. The `data-` prefix is always valid HTML5, while bare `hx-*` attributes may require a custom DTD or relaxed validation in conservative environments.

### Does htmx check parent elements when resolving attributes?

Yes. The resolution algorithm uses `elt.closest('[hx-' + name + '], [data-hx-' + name + ']')` to traverse up the DOM tree. This means you can define attributes on parent containers and have them apply to child elements, regardless of whether you use `hx-*` or `data-hx-*` syntax at each level.