•2 min read•Tutorial
HTMX Common Patterns: Infinite Scroll, Modals, and More
Master common UI patterns with HTMX including infinite scroll, modals, search, and live updates
HTMX Common Patterns
Learn how to implement common UI patterns with HTMX.
Pattern 1: Infinite Scroll
<span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"content"</span>></span>
<span class="hljs-comment"><!-- Initial items --></span>
<span class="hljs-tag"></<span class="hljs-name">div</span>></span>
<span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">hx-get</span>=<span class="hljs-string">"/items?page=2"</span>
<span class="hljs-attr">hx-trigger</span>=<span class="hljs-string">"revealed"</span>
<span class="hljs-attr">hx-swap</span>=<span class="hljs-string">"afterend"</span>
<span class="hljs-attr">hx-target</span>=<span class="hljs-string">"#content"</span>></span>
<span class="hljs-tag"><<span class="hljs-name">p</span>></span>Loading more...<span class="hljs-tag"></<span class="hljs-name">p</span>></span>
<span class="hljs-tag"></<span class="hljs-name">div</span>></span>
Pattern 2: Modal Dialog
<span class="hljs-tag"><<span class="hljs-name">button</span> <span class="hljs-attr">hx-get</span>=<span class="hljs-string">"/modal/edit/1"</span>
<span class="hljs-attr">hx-target</span>=<span class="hljs-string">"#modal"</span>
<span class="hljs-attr">hx-swap</span>=<span class="hljs-string">"innerHTML"</span>></span>
Edit
<span class="hljs-tag"></<span class="hljs-name">button</span>></span>
<span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"modal"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"modal"</span>></span><span class="hljs-tag"></<span class="hljs-name">div</span>></span>
<span class="hljs-comment"><!-- Server returns --></span>
<span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"modal-content"</span>></span>
<span class="hljs-tag"><<span class="hljs-name">h2</span>></span>Edit Item<span class="hljs-tag"></<span class="hljs-name">h2</span>></span>
<span class="hljs-tag"><<span class="hljs-name">form</span> <span class="hljs-attr">hx-put</span>=<span class="hljs-string">"/items/1"</span>></span>
<span class="hljs-comment"><!-- Form fields --></span>
<span class="hljs-tag"></<span class="hljs-name">form</span>></span>
<span class="hljs-tag"></<span class="hljs-name">div</span>></span>
Pattern 3: Live Search
<span class="hljs-tag"><<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"search"</span>
<span class="hljs-attr">name</span>=<span class="hljs-string">"query"</span>
<span class="hljs-attr">hx-get</span>=<span class="hljs-string">"/search"</span>
<span class="hljs-attr">hx-trigger</span>=<span class="hljs-string">"keyup changed delay:500ms"</span>
<span class="hljs-attr">hx-target</span>=<span class="hljs-string">"#results"</span>
<span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Search..."</span> /></span>
<span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"results"</span>></span><span class="hljs-tag"></<span class="hljs-name">div</span>></span>
Pattern 4: Inline Edit
<span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">hx-target</span>=<span class="hljs-string">"this"</span> <span class="hljs-attr">hx-swap</span>=<span class="hljs-string">"outerHTML"</span>></span>
<span class="hljs-tag"><<span class="hljs-name">span</span>></span>{{ item.name }}<span class="hljs-tag"></<span class="hljs-name">span</span>></span>
<span class="hljs-tag"><<span class="hljs-name">button</span> <span class="hljs-attr">hx-get</span>=<span class="hljs-string">"/edit/{{ item.id }}"</span>></span>Edit<span class="hljs-tag"></<span class="hljs-name">button</span>></span>
<span class="hljs-tag"></<span class="hljs-name">div</span>></span>
<span class="hljs-comment"><!-- Server returns when editing --></span>
<span class="hljs-tag"><<span class="hljs-name">form</span> <span class="hljs-attr">hx-put</span>=<span class="hljs-string">"/update/{{ item.id }}"</span>
<span class="hljs-attr">hx-target</span>=<span class="hljs-string">"this"</span>
<span class="hljs-attr">hx-swap</span>=<span class="hljs-string">"outerHTML"</span>></span>
<span class="hljs-tag"><<span class="hljs-name">input</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"name"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"{{ item.name }}"</span> /></span>
<span class="hljs-tag"><<span class="hljs-name">button</span>></span>Save<span class="hljs-tag"></<span class="hljs-name">button</span>></span>
<span class="hljs-tag"><<span class="hljs-name">button</span> <span class="hljs-attr">hx-get</span>=<span class="hljs-string">"/cancel/{{ item.id }}"</span>></span>Cancel<span class="hljs-tag"></<span class="hljs-name">button</span>></span>
<span class="hljs-tag"></<span class="hljs-name">form</span>></span>
Pattern 5: Form Validation
<span class="hljs-tag"><<span class="hljs-name">form</span> <span class="hljs-attr">hx-post</span>=<span class="hljs-string">"/submit"</span>></span>
<span class="hljs-tag"><<span class="hljs-name">input</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"email"</span>
<span class="hljs-attr">hx-post</span>=<span class="hljs-string">"/validate/email"</span>
<span class="hljs-attr">hx-trigger</span>=<span class="hljs-string">"blur"</span>
<span class="hljs-attr">hx-target</span>=<span class="hljs-string">"next .error"</span> /></span>
<span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"error"</span>></span><span class="hljs-tag"></<span class="hljs-name">span</span>></span>
<span class="hljs-tag"><<span class="hljs-name">button</span>></span>Submit<span class="hljs-tag"></<span class="hljs-name">button</span>></span>
<span class="hljs-tag"></<span class="hljs-name">form</span>></span>
Pattern 6: Polling
<span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">hx-get</span>=<span class="hljs-string">"/status"</span>
<span class="hljs-attr">hx-trigger</span>=<span class="hljs-string">"every 2s"</span>
<span class="hljs-attr">hx-swap</span>=<span class="hljs-string">"innerHTML"</span>></span>
Checking status...
<span class="hljs-tag"></<span class="hljs-name">div</span>></span>
Pattern 7: Dependent Dropdowns
<span class="hljs-tag"><<span class="hljs-name">select</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"country"</span>
<span class="hljs-attr">hx-get</span>=<span class="hljs-string">"/cities"</span>
<span class="hljs-attr">hx-target</span>=<span class="hljs-string">"#city-select"</span>></span>
<span class="hljs-tag"><<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"us"</span>></span>United States<span class="hljs-tag"></<span class="hljs-name">option</span>></span>
<span class="hljs-tag"><<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"ca"</span>></span>Canada<span class="hljs-tag"></<span class="hljs-name">option</span>></span>
<span class="hljs-tag"></<span class="hljs-name">select</span>></span>
<span class="hljs-tag"><<span class="hljs-name">select</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"city-select"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"city"</span>></span>
<span class="hljs-tag"><<span class="hljs-name">option</span>></span>Select country first<span class="hljs-tag"></<span class="hljs-name">option</span>></span>
<span class="hljs-tag"></<span class="hljs-name">select</span>></span>
Pattern 8: Optimistic Updates
<span class="hljs-tag"><<span class="hljs-name">button</span> <span class="hljs-attr">hx-post</span>=<span class="hljs-string">"/like"</span>
<span class="hljs-attr">hx-swap</span>=<span class="hljs-string">"outerHTML"</span>
<span class="hljs-attr">hx-disabled-elt</span>=<span class="hljs-string">"this"</span>></span>
<span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"htmx-indicator"</span>></span>Liking...<span class="hljs-tag"></<span class="hljs-name">span</span>></span>
Like ({{ count }})
<span class="hljs-tag"></<span class="hljs-name">button</span>></span>
These patterns cover 90% of common UI needs. Simple, effective, no JavaScript required!
👨💻
Jordan Patel
Web Developer & Technology Enthusiast