- no longer boost forms of type
dialog
- properly trigger the
htmx:trigger
event when an event is delayed or throttled - file upload is now fixed
- empty templates that are not used for oob swaps are no longer removed from the DOM
- request indicators are not removed when a full page redirect or refresh occurs
- elements that have been disabled for a request are properly re-enabled before snapshotting for history
- you can now trigger events on other elements using the
HX-Trigger
response header - The
.d.ts
file should now work properly
- Make the
/dist/htmx.esm.js
file themain
file inpackage.json
to make installing htmx smoother - Update
htmx.d.ts
& include it in the distribution - A fix to avoid removing text-only templates on htmx cleanup
- A fix for outerHTML swapping of the
body
tag - Many docs fixes
- Removed extensions and moved to their own repos linked off of https://extensions.htmx.org
- The website now supports dark mode! (Thanks @pokonski!)
- The older, deprecated SSE & WS attributes were removed
- Better support for Web Components & Shadow DOM
- HTTP
DELETE
requests now use parameters, rather than form encoded bodies, for their payload (This is in accordance w/ the spec.) - Module support was split into different files:
- We now provide specific files in
/dist
for the various JavaScript module styles:- ESM Modules:
/dist/htmx.esm.js
- AMD Modules:
/dist/htmx.amd.js
- CJS Modules:
/dist/htmx.cjs.js
- The
/dist/htmx.js
file continues to be browser-loadable
- ESM Modules:
- The
hx-on
attribute, with its special syntax, has been removed in favor of the less-hackyhx-on:
syntax. - See the Upgrade Guide for more details on upgrade steps
- The
selectAndSwap()
internal API method was replaced with the public (and much better)swap()
method
- Fix for new issue w/ web sockets & SSE on iOS 17.4 (thanks apple!)
- Fix for double script execution issue when using template parsing
- Fix TypeScript types file
- Fix SSE Ext: reinstantiate EventSource listeners upon reconnection logic (#2272)
hx-on*
attributes now support the formhx-on-
, with a trailing dash, to better support template systems (such as EJS) that do not like double colons in HTML attributes.- Added an
htmx.config.triggerSpecsCache
configuration property that can be set to an object to cache the trigger spec parsing - Added a
path-params.js
extension for populating request paths with variable values - Many smaller bug fixes & improvements
- Allow CSS selectors with whitespace in attributes like
hx-target
by using parens or curly-braces - Properly allow users to override the
Content-Type
request header - Added the
select
option tohtmx.ajax()
- Fixed a race condition in readystate detection that lead to htmx not being initialized in some scenarios with 3rd party script loaders
- Fixed a bug that caused relative resources to resolve against the wrong base URL when a new URL is pushed
- Fixed a UI issue that could cause indicators to briefly flash
- Fixed a few npm & build related issues
- Fixed a bug where a button associated with a form that is swapped out of the DOM caused errors
- The
hx-target-error
attribute was added to theresponse-targets
extension, allowing you to capture all 400 & 500 responses with a single attribute hx-on
now properly supports multiple listeners- The
hx-confirm
prompt is now passed into custom confirmation handlers next
andprevious
are now valid extended CSS symbols in htmx- The
htmx:beforeHistoryUpdate
event was added - Properly ignore the
dialog
formmethod on buttons when resolving the HTTP method to use - Added a
htmx.config.scrollIntoViewOnBoost
option that may be set tofalse
to disable scrolling the top of the body into view for boosted elements
- IE support has been restored (thank you @telroshan!)
- Introduced the
hx-disabled-elt
attribute to allow specifying elements to disable during a request - You can now explicitly decide to ignore
title
tags found in new content via theignoreTitle
option inhx-swap
and thehtmx.config.ignoreTitle
configuration variable. hx-swap
modifiers may be used without explicitly specifying the swap mechanism- Arrays are now supported in the
client-side-templates
extension - XSLT support in the
client-side-templates
extension - Support
preventDefault()
in extension event handling - Allow the
HX-Refresh
header to apply even after anHX-Redirect
has occurred - the
formaction
andformmethod
attributes on buttons are now properly respected hx-on
can now handle events with dots in their namehtmx.ajax()
now always returns a Promise- Handle leading
style
tag parsing more effectively
- Web sockets now properly pass the target id in the HEADERS struct
- A very rare loading state bug was fixed (see https://github.com/bigskysoftware/htmx/commit/93bd81b6d003bb7bc445f10192bdb8089fa3495d)
hx-on
will not evaluate ifallowEval
is set to false- You can disable the interpretation of script tags with the new
htmx.config.allowScriptTags
config variable - You can now disable htmx-based requests to non-origin hosts via the
htmx.config.selfRequestsOnly
config variable - The Security section has been expanded to help developers better understand how to properly secure their htmx-based applications.
- This is a bug-fix release for the most part, w/a heavy dose of @telroshan
- The
HX-Trigger
response header now supports comma separated event names - Submit buttons that use the
form
attribute now work correctly - The
changed
modifier now uses the triggering element, rather than the element thehx-trigger
is defined on hx-disable
is now handled dynamically so it can be added and removed- IE11 compatibility restored! (maybe, hard to test)
- Fixed bug with
hx-on
event handler cleanup - Many smaller bug fixes, typo fixes and general improvements
- The
hx-on
attribute has been deprecated (sorry) in favor ofhx-on:<event name>
attributes. Seehx-on
for more information. - We now have functioning CI using GitHub actions!
- You can now configure if a type of HTTP request uses the body for parameters or not. In particular, the
DELETE
should use query parameters, according to the spec. htmx has used the body, instead. To avoid breaking code we are keeping this undefined behavior for now, but allowing people to fix it for their use cases by updating thehtmx.config.methodsThatUseUrlParams
config option. Thank you to Alex and Vincent for their feedback and work on this issue! - The
this
symbol is now available in event filter expressions, and refers to the element thehx-trigger
is on - Fix bug where the
htmx:afterSettle
event was raised multiple times with oob swaps occurred - A large number of accessibility fixes were made in the docs (Thank you Denis & crew!)
- Fixed bug w/ WebSocket extension initialization caused by "naked"
hx-trigger
feature - The
HX-Reselect
HTTP response header has been added to change the selection from the returned content - Many other smaller bug fixes
- Fixed bug w/
hx-on
not properly de-initializing
- Fixed a bug with the new naked triggers that prevented boosted elements with explicit
hx-trigger
's from functioning properly - Added code to play well with other libraries that also use the
window.onpopstate
Daily reminder: https://htmx.org/img/memes/javascripthistory.png
- Support for generalized inline event handling via the new
hx-on
attribute, which addresses the shortcoming of limitedonevent
properties attributes in HTML. - Support for view transitions, based on the experimental View Transitions API currently available in Chrome 111+ and coming to other browsers soon.
- Support for "naked"
hx-trigger
attributes, where anhx-trigger
is present on an element that does not have anhx-get
, etc. defined on it. Instead, it will trigger the newhtmx:triggered
event, which can be responded to via your preferred scripting solution. - A memory leak fix by @croxton
- The htmx website has been migrated from 11ty to zola by @danieljsummers, cutting way down on the number of "development" javascript dependencies
- Many other smaller bug fixes
- ESM support!
- Sass has been vanquished from the htmx.org website, which should set us up for some good progress going forward
- Fixed a bug where the
changed
modifier onkeyup
did not work properly if an input was tabbed into - Many other smaller bug fixes and doc fixes
- Support a new optional cache-busting configuration option,
getCacheBusterParam
, to allow browsers to disambiguate betweenGET
requests from htmx and from the raw browser - Support new
hx-history='false'
attribute, to prevent sensitive data from being stored in the history cache. (Thank you @croxton!) - Extensive new event-oriented features are available in the Web Socket extension (Thank you @Renerick!)
- A bug fix for when a form contains multiple empty input values with the same name (Thank you @bluekeyes!)
- A bug fix around inputs that throw exceptions when calling
setSelectionRange()
(Thank you @gone!) - A bug fix to pass through the proper event for the
htmx:configRequest
event - A bug fix/improvement for the
preload
extension - Many other small bug fixes
- Fix the exact same regression in
revealed
logic as in 1.8.2
- A new
htmx:confirm
event was added that allows for asynchronous confirmation dialogs to be integrated into htmx requests - The new head-support extension allows for more elaborate head tag merging than standard htmx supports. This functionality may be integrated into htmx 2.0, depending on feedback.
- The new multi-swap provides more elaborate swapping of multiple elements on a screen using a custom swap strategy
- Many doc fixes (thank you to everyone who contributed!)
- Fix regression in
revealed
logic
- We now keep a count of outstanding requests for an indicator, so more than one overlapping request can share the same indicator without issues
- We now track the attribute state of an element and re-initialize it if
htmx.process()
is called on the element and the attributes have changed - Idiomorph is now available for all your morph-swapping needs
- The
unset
directive now works properly forhx-vals
andhx-vars
- The title of the page is now properly set on a history cache miss
- The new
hx-validate
attribute will force elements to validate before a request, even if they are not within a form being submitted - Many smaller bug and docs fixes
- NOTE: This release involved some changes to touchy code (e.g. history support) so please test thoroughly and let us know if you see any issues
- Boosted forms now will automatically push URLs into history as with links. The response URL
detection API support is good enough that we feel comfortable making this the default now.
- If you do not want this behavior you can add
hx-push-url='false'
to your boosted forms
- If you do not want this behavior you can add
- The
hx-replace-url
attribute was introduced, allowing you to replace the current URL in history (to complementhx-push-url
) - Bug fix - if htmx is included in a page more than once, we do not process elements multiple times
- Bug fix - When localStorage is not available we do not attempt to save history in it
- Bug fix -
hx-boost
respects theenctype
attribute m
is now a valid timing modifier (e.g.hx-trigger="every 2m"
)next
andprevious
are now valid extended query selector modifiers, e.g.hx-target="next div"
will target the next div from the current element- Bug fix -
hx-boost
will boost anchor tags with a_self
target - The
load
event now properly supports event filters - The websocket extension has had many improvements: (A huge thank you to Denis Palashevskii, our newest committer on the project!)
- Implement proper
hx-trigger
support - Expose trigger handling API to extensions
- Implement safe message sending with sending queue
- Fix
ws-send
attributes connecting in new elements - Fix OOB swapping of multiple elements in response
- Implement proper
- The
HX-Location
response header now implements client-side redirects entirely within htmx - The
HX-Reswap
response header allows you to change the swap behavior of htmx - The new
hx-select-oob
attribute selects one or more elements from a server response to swap in via an out of band swap - The new
hx-replace-url
attribute can be used to replace the current URL in the location bar (very similar tohx-push-url
but no new history entry is created). The correspondingHX-Replace-Url
response header can be used as well. - htmx now properly handles anchors in both boosted links, as well as in
hx-get
, etc. attributes
- The new
hx-sync
attribute allows you to synchronize multiple element requests on a single element using various strategies (e.g. replace)- You can also now abort an element making a request by sending it the
htmx:abort
event
- You can also now abort an element making a request by sending it the
- Server Sent Events and Web Sockets are now available as
extensions, in addition to the normal core support. In htmx 2.0, the current
hx-sse
andhx-ws
attributes will be moved entirely out to these new extensions. By moving these features to extensions we will be able to add functionality to both of them without compromising the core file size of htmx. You are encouraged to move over to the new extensions, buthx-sse
andhx-ws
will continue to work indefinitely in htmx 1.x. - You can now mask out attribute inheritance via the
hx-disinherit
attribute. - The
HX-Push
header can now have thefalse
value, which will prevent a history snapshot from occurring. - Many new extensions, with a big thanks to all the contributors!
- A new
alpine-morph
allows you to use Alpine's swapping engine, which preserves Alpine - A restored extension was added that will trigger a
restore
event on all elements in the DOM on history restoration. - A loading-states extension was added that allows you to easily manage loading states while a request is in flight, including disabling elements, and adding and removing CSS classes.
- A new
- The
this
symbol now resolves properly for thehx-include
andhx-indicator
attributes - When an object is included via the
hx-vals
attribute, it will be converted to JSON (rather than rendering as the string[Object object]"
) - You can now pass a swap style in to the
htmx.ajax()
function call. - Poll events now contain a
target
attribute, allowing you to filter a poll on the element that is polling. - Two new Out Of Band-related events were added:
htmx:oobBeforeSwap
&htmx:oobAfterSwap
- A new
HX-Retarget
header allows you to change the default target of returned content - The
htmx:beforeSwap
event now includes another configurable property:detail.isError
which can be used to indicate if a given response should be treated as an error or not - The
htmx:afterRequest
event has two new detail properties:success
andfailed
, allowing you to write trigger filters in htmx or hyperscript:on htmx:afterRequest[failed] set #myCheckbox's checked to true
- Fixed the
from:
option inhx-trigger
to supportclosest <CSS selector>
andfind <CSS selector>
forms - Don't boost anchor tags with an explicit
target
set - Don't cancel all events on boosted elements, only the events that naturally trigger them (click for anchors, submit for forms)
- Persist revealed state in the DOM so that on history navigation, revealed elements are not re-requested
- Process all
hx-ext
attributes, even if no other htmx attribute is on the element - Snapshot the current URL on load so that history support works properly after a page refresh occurs
- Many, many documentation updates (thank you to all the contributors!)
- Completely reworked
<script>
tag support that now supports the<script src="...'/>
form - You can now use the value
unset
to clear a property that would normally be inherited (e.g. hx-confirm) - The
htmx-added
class is added to new content before a swap and removed after the settle phase, which allows you more flexibility in writing CSS transitions for added content (rather than relying on the target, as withhtmx-settling
) - The
htmx:beforeSwap
event has been updated to allow you to configure swapping behavior - Improved
<title>
extraction support - You can listen to events on the
window
object using thefrom:
modifier inhx-trigger
- The
root
option of theintersect
event was fixed - Boosted forms respect the
enctype
declaration - The
HX-Boosted
header will be sent on requests from boosted elements - Promises are not returned from the main ajax function unless it is an api call (i.e.
htmx.ajax
)
- Support tracking of button clicked during a form submission
- Conditional polling via the hx-trigger attribute
document
is now a valid pseudo-selector on the hx-triggerfrom:
argument, allowing you to listen for events on the document.- Added the hx-request attribute, allowing you to configure the following aspects of the request
timeout
- the timeout of the requestcredentials
- if the request will send credentialsnoHeaders
- strips all headers from the request
- Along with the above attribute, you can configure the default values for each of these via the corresponding
htmx.config
properties (e.g.htmx.config.timeout
) - Both the
scroll
andshow
options on hx-swap now support extended syntax for selecting the element to scroll or to show, including the pseudo-selectorswindow:top
andwindow:bottom
.
- typo fix
- Added the
queue
option to the hx-trigger attribute, allowing you to specify how events should be queued when they are received with a request in flight - The
htmx.config.useTemplateFragments
option was added, allowing you to use HTML template tags for parsing content from the server. This allows you to use Out of Band content when returning things like table rows, but it is not IE11 compatible. - The
defaultSettleDelay
was dropped to 20ms from 100ms - Introduced a new synthetic event, intersect that allows you to trigger when an item is scrolled into view
as specified by the
IntersectionObserver
API - Fixed timing issue that caused exceptions in the
reveal
logic when scrolling at incredible speeds - #463 - Fixed bug causing SVG titles to be incorrectly used as page title - #459
- Boosted forms that issue a GET will now push the URL by default - #485
- Better dispatch of request events when an element is removed from the DOM
- Fixed a bug causing
hx-prompt
to fail - The
htmx.config.withCredentials
option was added, to send credentials with ajax requests (default isfalse
) - The
throttle
option onhx-trigger
does not delay the initial request any longer - The
meta
key is ignored on boosted links <script>
tags are now evaluated in the global scopehx-swap
now supports thenone
option- Safari text selection bug - #438
- Added the
hx-disabled
attribute to allow htmx to be turned off for parts of the DOM - SSE now uses a full-jitter exponential backoff algorithm on reconnection, using the
htmx.config.wsReconnectDelay
setting
- Bug fixes
- IE11 fixes
- Support a
target
modifier onhx-trigger
to filter based on the element targeted by an event. This allows lazy binding to that target selector. - Events are no longer consumed by the first element that might handle them, unless the
consume
keyword is added to thehx-trigger
specification - Added the
htmx:beforeSend
event, fired just before an ajax request begins - SSE swaps are properly settled
- Fixed bug that was improperly cancelling all clicks on anchors
htmx.ajax()
now returns a promise
- Fixed an issue with the history cache, where the cache was getting blown out after the first navigation backwards
- Added the
htmx.config.refreshOnHistoryMiss
option, allowing users to trigger a full page refresh on history cache miss rather than issuing an AJAX request
hx-vars
has been deprecated in favor ofhx-vals
hx-vals
now supports ajavascript:
prefix to achieve the behavior thathx-vars
provided- The new
hx-headers
attribute allows you to add headers to a request via an attribute. Likehx-vals
it supports JSON or javascript via thejavascript:
prefix hx-include
will now include all inputs under an element, even if that element is not a form tag- The preload extension now offers a
preload-images="true"
attribute that will aggressively load images in preloaded content - On requests driven by a history cache miss, the new
HX-History-Restore-Request
header is included so that the server can differentiate between history requests and normal requests
- Improved handling of precedence of input values to favor the enclosing form (see here)
- Moved event filtering logic after
preventDefault
so filtering still allows events to be properly handled - No longer trigger after swap events on elements that have been removed via an
outerHTML
swap - Properly remove event handlers added to other elements when an element is removed from the DOM
- Handle the
scroll:
modifier inhx-swap
properly when anouterHTML
swap occurs - Lots of docs fixes
- Newly added preload extension allows you to preload resources for lower latency requests!
- Support the
ignore:
modifier for extensions - Updated form variable order inclusion to include the enclosing form last so that, in the presence of multiple values, the most relevant value is the most likely to be selected by the server
- Support for the
htmx.ajax()
javascript function, to issue an htmx-style ajax request from javascript - Removed the following htmx request headers for better cache behavior:
HX-Event-Target
,HX-Active-Element
,HX-Active-Element-Name
,HX-Active-Element-Value
- Added the
hx-preserve
attribute, which allows you to preserve elements across requests (for example, to keep a video element playing properly) - The path-deps now surfaces a small api for refreshing path dependencies manually in javascript
- Now support the
from:
clause onhx-trigger
to allow an element to respond to events on other elements. - Added the
htmx:beforeProcessNode
event, renamed the (previously undocumented)htmx:processedNode
tohtmx:afterProcessNode
- Added
closest
syntax support for thehx-indicator
attribute - Added
on load
support for the newest version of hyperscript - Added the
htmx.config.allowEval
configuration value, for CSP compatibility - Bug fixes & improvements
- Extend all API methods to take a string selector as well as an element
- Out of band swap elements need not be top level now
hx-swap-oob
now can accept a CSS selector to retarget with
- AJAX file upload now correctly fires events, allowing for a proper progress bar
- htmx api functions that expect an element now can accept a string selector instead:
htmx.on('#form', 'htmx:xhr:progress', function(evt) { htmx.find('#progress').setAttribute('value', evt.detail.loaded/evt.detail.total * 100) });
- htmx now properly handles the
multiple
attribute on<select>
elements
- Bumped the release version :)
- Fixed bug with title tag support when title tag contained HTML entities
- Pass properties for the
loadstart
,loadend
,progress
,abort
events through properly to the htmx equivalents
- Now support the
HX-Redirect
andHX-Refresh
response headers for redirecting client side and triggering a page refresh, respectively hx-vars
now overrides input values<title>
tags in responses will be used to update page titles- All uses of
eval()
have been removed in favor ofFunction
hx-vals
is available as a safe alternative tohx-vars
. It usesJSON.parse()
rather than evaluation, if you wish to safely pass user-provided values through to htmx.
hx-trigger
parsing has been rewritten and now supports trigger filters to filter events based on arbitrary javascript expressions- htmx now supports two additional response headers
HX-Trigger-After-Swap
andHX-Trigger-After-Settle
allowing an event to be triggered after a given life cycle event (instead of before the swap) - The
requestConfig
is now passed out to events surrounding the AJAX life cycle - htmx now evaluates
<script>
tags as javascript when no language is defined on them - A new
event-header
extension, which will include a serialized JSON representation of the triggering event in requests
- BREAKING CHANGE: The SSE attribute
hx-sse
and the Web Sockets attributehx-ws
have changed syntax to now use colon separators:hx-sse='connect:/chat swap:message'
- The SSE attribute
hx-sse
allows for swapping content directly on an event, in addition to triggering an htmx element, with the newswap:<event name>
syntax. hx-target
now supports afind
syntax to find elements below the element by a CSS selector- htmx plays better with deferred loading and many package managers
- All htmx events are dispatched in both camelCase as well as kebab-case, for better compatibility with AlpineJS and other frameworks. (e.g.
htmx:afterOnLoad
will also be triggered ashtmx:after-on-load
) - hypeerscript is now initialized independently of htmx
- The
view
modifier onhx-swap
has been renamed toshow
:hx-swap='innerHTML show:top'
- The
hx-swap
attribute now supports two new modifiers:scroll
- allows you to scroll the target to thetop
orbottom
view
- allows you to scroll thetop
orbottom
of the target into view
- The
hx-push-url
attribute now can optionally take a URL to push, in addition totrue
andfalse
- Added the
hx-vars
attribute that allows you to dynamically add to the parameters that will be submitted with a request
- Custom request/response headers no longer start with the
X-
prefix, which is no longer recommended - empty verb attributes are now allowed and follow the anchor tag semantics (e.g.
<div hx-get></div>
) - nunjuks inline rendering is now supported in the
client-side-templates
extension - the new
ajax-header
extension includes theX-Requested-With
header - bad JSON is now handled more gracefully
hx-swap="none"
will cause no swap to take place #89hx-trigger
now supports athrottle
modifier #88- the focused element is preserved if possible after a replacement
- perf improvements for large DOM trees with sparse
hx-
annotations
- Extension mechanism added
- SSE support added
- WebSocket support added
- Renamed to htmx
- A bug fix for the
hx-prompt
attribute - A bug fix for multiple
hx-swap-oob
attributes - Moved the default CSS indicator injection into its own sheet to avoid breaking
- Added the
htmx.config.includeIndicatorStyles
configuration option so people can opt out of injecting the indicator CSS
- Initial release (originally named kutty)