upvote
You can always make the server-side render partials based on a request header.

https://github.com/dsego/ssr-playground/blob/main/src/server...

reply
That is what I did. I was using Astro which has full support for partial HTML via the router
reply
I think I understand now, even the partial required submitting everything to the server, which can be skipped if you can have interactivity without unnecessary requests.
reply
Exactly. The partial response was 100kb-200kb of HTML + the backend query time. Of course, depending on your filters. But a large chunk of that was just sending down the form on the left side, which I already had on page load, so that penalty was real.

It was only the right side results of the experience that needed to be refetched when the form changed.

But in HTMX, you are expected to just send the whole dang thing back for every change. Makes sense for a like-button, a dialog, or even a classic form submission.

My refactor cut the HTML response by about 70kb and that made a big difference. The form became fully static and I had a simple Alpine data component that would just sync that state with the URL. Still used a GET on the form and still used the same partial endpoint. Just way less HTML to wait for.

reply
Unless there's a material change to the form, why not just update the changed parts?

I'd also question architectural decisions if you need to send 100kb+ of html down the wire for a partial.

reply
Thats not on htmx to decide what html to resend that's your engineering work...
reply
Why are you expected to send down the whole thing? Maybe I’m missing something, but when you send the request from the form the response is just a partial of the results on the right hand side, using hx-target to specify some div instead of replacing the form. Form just stays there?
reply
To sync the form state based on the current selections in the form. This is often called facets. The form contained many options and as you filtered those options would change. So you need a way to update the form too. Hence, compute the full thing on the server (the form state, the options within the fields, and the results) then send it all back.
reply
Except you don't. Use hx-vals, hx-include, or even hx-headers to pull in additional data into the request that's outside of the immediate form/component.
reply
I can't really understand what you're describing. You have form on left & results on right, but you're requesting the new form state & re-rendering the form HTML on each request? Why? My naive understanding is that you could use something like hx-target to have the response to the form submissions update only the results area & the form should not need rerendered at all.

Why does the form need rerendered on a per request basis? HTML/Browser already tracks the current form state.

reply
AJAX is old tech though, using stuff that worked in the year 2000 is cheating in 2026. You are supposed to make the site slow and bloated for some reason.
reply
It isn’t literally AJAX. Just a catchy name. It is just a fetch wrapper that mimics the $get, $post, etc. API
reply
Despite the fact that HTMX is a good solution in many cases, it's not the best solution in all cases. Ditto for React, and for any technology actually. Planning and consideration are always required, if you care about the end result.
reply
Is there a reason why you don't have an endpoint + template that renders only the result list. The form could be separate thing and issue a form submit request with all the selected filters? Seems better than rendering the whole page. You could even display a loader while the results are loading, and swap the list html element on success.
reply
That is what I ended up doing but once I did that, I had a hell of a time getting that dynamic form working well with just the HTMX primitives. I even tried to do two different partials that would be fetched when I needed each one to rerender.

The gist of what I was saying was that once I had a more complicated experience, the benefits of just fetching a fresh partial each time started to dwindle. The HTML response grew, I needed a bunch of inline handlers to patch over some state issues, as well as the complexity of the template, just started to be too much. Really it was the Alpine part that I was missing. Simple class toggles, easy way to toggle aria attributes, show/hide for elements, and reactive/computed values, were the things I needed to get the results the client wanted.

If I was building a simple search input + results, I would use HTMX all day. These forum people make it work and that seems like a great use case. But it just didn’t fit with a more sophisticated form that had dynamic options plus a large results display and the burden of a slower query to just get the data.

reply
have a look at https://segor.de/ - it just downloads 2MB of product listing data (pre-dating JSON!) and then does all filtering client-side
reply
[dead]
reply
You swapped out HTMX because you couldn’t figure out how to load a list of items gradually instead of all at once??
reply
If I wanted to do that I would have added pagination. But that UX also sucks in a different way.

I think dynamically fetching results (ala infinite scroll) would have been more complicated to build. I would have had to add an intersection detection (HTMX 4 has that) to trigger the form/request again, but with an ever increasing chunk offset slice. I also need a way to track that state as well. Considering I had one big HTML response, I don’t think I could have done that efficiently without splitting it anyway. Even if I could "pluck" the results I needed from the HTML response, the penalty of waiting for the response was the factor.

If you have any links to some demos where there is something like that, I would appreciate it.

All that being said, the count of items actually isn't the most relevant part. The most relevant part is the amount of HTML per single result. If you have a sophisticated card component (a title, a description, images, a table of information inside of it or complicated layout) just loading six cards could end up being hundreds of HTML elements.

So even if you lazy loaded elements in chunks, those chunks are still gonna take a while to fetch given the size of the HTML. You also break CTRL-F-ing since those results don’t exist in the DOM until you trigger their fetching code. Same problem as classic pagination.

I would have to completely refactor my entire experience regardless because if I want to lazily load the cards/results gradually, I would have to split up the layout to make it more efficient.

So my approach to shrink the HTML response was to break it up the "live" section to just the right half.

reply
Infinite scroll is a shit pattern it creates complexity and makes it hard to get back to a position on the generated and changeable list. It can also be unexpected slow. Everyone knows a page load can be slow if their Internet is slow but a slow down when scrolling feels janky.If you think you need it you need pagination and more importantly better filters and search so users can find stuff easier without 200 options.
reply
Want to help rather than throw tomatoes?
reply
It was a genuine question. I’ve implemented infinite scrolling in HTMX and it’s quite easy, another commenter posted an example from the HTMX docs and it’s a couple of lines of html.
reply
Wouldn't constantly loading new items into a select form be super annoying? Can HTML even keep a select input open when new items are added?
reply
deleted
reply