Home >Web Front-end >JS Tutorial >An Introduction to htmx, the HTML-focused Dynamic UI Library
Modern web users expect a smooth and dynamic single-page application (SPA) experience. However, creating a SPA often requires complex frameworks like React and Angular, and learning and using them can be complex. htmx came into being - it is a library that provides a new perspective for building dynamic web experiences by leveraging features such as Ajax and CSS transitions directly in HTML.
This guide will explore the capabilities of htmx, how it simplifies dynamic web development, and how it can leverage its potential to enhance your web development process.
Developers have traditionally two main options when building interactive web experiences, each with its own tradeoffs. On the one hand, there are multi-page applications (MPAs) that refresh the entire page every time the user interacts with it. This approach ensures that the server controls the application state and that the client faithfully expresses it. However, full page reloading results in a slow and clumsy user experience.
On the other hand, single page applications (SPAs) rely on JavaScript running in the browser to manage application state. They communicate with the server using API calls, which return data, usually in JSON format. The SPA then uses this data to update the user interface without page refresh, providing a smoother user experience, somewhat similar to native desktop or mobile apps. However, this approach is not perfect either. Computation overhead is usually higher due to large client processing; initial loading time may be slower because clients must first download and parse large JavaScript packages to render the first page; setting up a development environment often requires handling complex build tools and workflows .
htmx provides a compromise for both extreme situations. It provides the user experience advantage of SPA – without full page reloading – while maintaining the server-side simplicity of MPA. In this model, the server does not return the data that the client needs to interpret and render, but but an HTML fragment . Then, htmx simply replaces these snippets to update the user interface.
This approach simplifies the development process by minimizing client complexity and the large number of JavaScript dependencies commonly used by SPAs. It requires no complicated setup and provides a smooth and responsive user experience.
There are multiple ways to include htmx in your project. You can download it directly from your project's GitHub page, or if you're using Node.js, you can install it via npm using the command npm install htmx.org.
However, the easiest way (the one that will be used in this guide) is to include it through a Content Delivery Network (CDN). This allows us to start using htmx without any setup or installation process. Simply include the following script tag in your HTML file:
<code class="language-html"></code>
This script tag points to version 1.9.4, but if a newer version is available, you can replace "1.9.4" with the latest version.
htmx is very lightweight, with a minimum and gzip version weighing about ~14KB. It has no dependencies and is compatible with all major browsers, including IE11.
After adding htmx to your project, you may want to check if it works properly. You can test it with the following simple example:
<code class="language-html"><button hx-get="https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode&type=single" hx-target="#joke-container"> Make me laugh! </button> <p id="joke-container">Click the button to load a joke...</p></code>
When clicking the button, if htmx works properly, it will send a GET request to the Joke API and replace it with the server's response. Contents of
tags.
Consider the following:
<code class="language-html"><button hx-get="/api/resource">Load Data</button></code>In the example above, the button element is assigned an hx-get property. After clicking the button, a GET request is made to the /api/resource URL.
What happens after the server returns data? By default, htmx will inject this response directly into the startup element—in our example, a button. However, htmx is not limited to this behavior and provides the ability to specify response data as the target element. We will explore this feature more in-depth in the next sections.
Trigger request with htmx
Let's demonstrate this by extending the joke example above, allowing the user to search for jokes containing specific words:
<code class="language-html"></code>
To trigger a search, we need to trigger a change event. For The results will now be updated immediately. This is good, but it introduces a new problem: we are now using API calls with every key press. To avoid this, we can use modifiers to change the behavior of the trigger. htmx provides the following: In this case, we seem to need delay: Now when you type something in the box (trying to use a longer word, such as "developer"), the request will only be triggered if you pause or finish typing. As you can see, this allows us to implement the active search box pattern with just a few lines of client code. In web development, user feedback is crucial, especially in operations that may take a lot of time to complete (such as issuing network requests). A common way to provide this feedback is through a request indicator—a visual prompt indicating that the operation is in progress. htmx integrates support for request indicators, allowing us to provide this feedback to users. It uses the hx-indicator class to specify the element used as the request indicator. The opacity of any element with this class defaults to 0, making it invisible but present in the DOM. When htmx makes an Ajax request, it applies the htmx-request class to the startup element. The htmx-request class will cause the element (or any child element with the htmx-indicator class) to transition to an opacity of 1. For example, consider an element that uses a load spinner as its request indicator: When a button with the hx-get attribute is clicked and the request is initiated, the button receives the htmx-request class. This causes the image to be displayed until the request is completed and the class is deleted. You can also use the htmx-indicator property to indicate which element should receive the htmx-request class. Let's demonstrate this with our Joke API example: Note: We can get the CSS style of the spinner from the CSS loader and spinner. There are many to choose from; receive HTML and CSS with just one click. This will cause the load spinner to appear when the request is in progress. If our network is fast, the spinner will only blink briefly when the request is made. If we want to make sure it does exist, we can use the browser's development tools to limit our network connection speed. Or, just for fun (that is, don't do this in real applications), we can configure htmx to simulate some network latency: This takes advantage of the event system of htmx, which we can use to modify and enhance its behavior. Here we use the htmx:afterOnLoad event, which fires after Ajax onload completes. I also used a sleep function from the SitePoint article about the same topic. This is a finished demo. Type something in the box (such as "JavaScript") and then observe the load indicator after starting the request. As you can see, this allows us to implement the active search box pattern with just a few lines of client code. In some cases, we may want to update an element that is different from the one that initiates the request. htmx allows us to use the hx-target attribute to locate specific elements for Ajax response. This property can take a CSS selector, which htmx will use to find the elements to be updated. For example, if we have a form that posts new comments to our blog, we might want to attach new comments to the comment list instead of updating the form itself. We actually saw this in the first example: button does not replace its own content, but the hx-target property declares that the response should replace the content of the element with ID "joke-container". htmx also provides some more advanced methods to select elements to which content should be loaded. These include this, closest, next, previous and find. Referring to our previous example, we can also write hx-target="next p" to avoid specifying the ID. By default, htmx will replace the contents of the target element with an Ajax response. But what if we want to attach new content instead of replacing it? This is where the hx-swap attribute comes in. This property allows us to specify how new content is inserted into the target element. Possible values are outerHTML, innerHTML, beforebegin, afterbegin, beforeend, and afterend. For example, using hx-swap="beforeend" will add new content to the end of the target element, which is perfect for our new comment scenario. CSS transition allows the style of an element to be changed smoothly from one state to another without using JavaScript. These transitions can be as simple as color changes or as complex as a complete 3D transformation. htmx makes it easy to use CSS in our code: we just need to maintain consistent element IDs in HTTP requests. Consider this HTML content: After making an htmx Ajax request to /new-content, the server returns the following: Although the content has changed, <input>
elements, this happens when the element's value changes and loses focus. So, type something in the box (such as "bar"), click elsewhere on the page, and the joke will appear in the <input>
element:
<code class="language-html"><button hx-get="https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode&type=single" hx-target="#joke-container">
Make me laugh!
</button>
<p id="joke-container">Click the button to load a joke...</p></code>
<code class="language-html"><button hx-get="/api/resource">Load Data</button></code>
Request indicator
<code class="language-html"></code>
<code class="language-html"><button hx-get="https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode&type=single" hx-target="#joke-container">
Make me laugh!
</button>
<p id="joke-container">Click the button to load a joke...</p></code>
<code class="language-html"><button hx-get="/api/resource">Load Data</button></code>
Target elements and content exchange
<code class="language-html"><label for="contains">Keyword:</label>
<input type="text" placeholder="Enter a keyword..." hx-get="https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode" hx-target="#joke-container" name="contains">
<p id="joke-container">Results will appear here</p></code>
The Extended CSS selector
Content Exchange
CSS Transition in htmx
<code class="language-html"></code>
<code class="language-html"><button hx-get="https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode&type=single" hx-target="#joke-container">
Make me laugh!
</button>
<p id="joke-container">Click the button to load a joke...</p></code>
<div> maintains the same ID. However, the fadeIn class has been added to the new content. We can now create a CSS transition that smoothly transitions from the initial state to the new state:
<pre class="brush:php;toolbar:false"><code class="language-html"><button hx-get="/api/resource">Load Data</button></code></pre>
<p> When htmx loads new content, it triggers the CSS transition, creating a smooth visual progress to the updated state. </p>
<h3>Use View Transition API</h3>
<p>The new View Transition API provides a way to animate between different states of a DOM element. Unlike CSS transitions, which involve changing the CSS properties of an element, view transitions are about animate the content of an element. </p>
<p>The View Transition API is a new experimental feature that is currently under active development. At the time of writing, this API is implemented in Chrome 111 and more browsers are expected to add support in the future (you can check their support on caniuse). htmx provides an interface for using the View Transition API and fallback to a non-transition mechanism in browsers that do not support APIs. </p>
<p>In htmx, there are two ways to use the View Transition API: </p>
<ul>
<li>Set the htmx.config.globalViewTransitions configuration variable to true. This will use transitions for all exchanges. </li>
<li> Use the transition:true option in the hx-swap property. </li>
</ul>
<p>View transitions can be defined and configured using CSS. Here is an example of a "bounce" transition where old content bounces out and new content bounces in: </p>
<pre class="brush:php;toolbar:false"><code class="language-html"><label for="contains">Keyword:</label>
<input type="text" placeholder="Enter a keyword..." hx-get="https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode" hx-target="#joke-container" name="contains">
<p id="joke-container">Results will appear here</p></code></pre>
<p>In the htmx code, we use the transition:true option in the hx-swap property and apply the bounce-it class to what we want to animate it: </p>
<pre class="brush:php;toolbar:false"><code class="language-html">...
hx-trigger="keyup"
...</code></pre>
<p>In this example, when the content of <code><div> is updated, the old content will bounce out and the new content will bounce in, creating a pleasant and engaging visual effect.
<p> Remember that for the moment, this demo is only available for Chromium-based browsers. </p>
<h2>Form Verification</h2>
<p>htmx integrates well with the HTML5 verification API and will prevent form requests from being sent if user input verification fails. </p>
<p>For example, when a user clicks Submit, a POST request is sent to /contact only if the input field contains a valid email address: </p>
<pre class="brush:php;toolbar:false"><code class="language-html"></code></pre>
<p>If we want to go a step further, we can add some server-side verification to make sure that only gmail.com is accepted: </p>
<pre class="brush:php;toolbar:false"><code class="language-html"><button hx-get="https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode&type=single" hx-target="#joke-container">
Make me laugh!
</button>
<p id="joke-container">Click the button to load a joke...</p></code></pre>
<p>Here, we add a parent element (div#wrapper) that declares itself as the recipient of the request (using this keyword) and uses the outerHTML exchange policy. This means that the entire <code><div> will be replaced by the server's response, even if it is not the element that actually triggers the request. We also added hx-post="/contact/email" to the input field, which means that whenever this field is blurred, it sends a POST request to the /contact/email endpoint. This request will contain the value of our field.
<p>On the server side (in /contact/email), we can use PHP to verify: </p>
<pre class="brush:php;toolbar:false"><code class="language-html"><button hx-get="/api/resource">Load Data</button></code></pre>
<p>As you can see, htmx expects the server to return HTML (<em> not </em> JSON) and insert it into the specified location in the page. </p>
<p>If we run the code above, type a non-gmail.com address into the input, and then make the input lose focus, an error message will appear below the field stating "Only Gmail addresses accepted!"</p>
<p><em>Note: When dynamically inserting content into the DOM, we should also consider how the screen reader interprets this content. In the example above, the error message is inside our tag, so the screen reader will read the field the next time it gets focus. If the error message is inserted elsewhere, we should associate it with the correct field using the aria-describedby property. </em></p>
<p>It is also worth noting that htmx triggers a set of events during the verification process, which we can use to add our own verification logic and error handling methods. For example, if we want to implement email checking in JavaScript code, we can do this: </p>
<pre class="brush:php;toolbar:false"><code class="language-html"><label for="contains">Keyword:</label>
<input type="text" placeholder="Enter a keyword..." hx-get="https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode" hx-target="#joke-container" name="contains">
<p id="joke-container">Results will appear here</p></code></pre>
<p>Here, we use the htmx:validation:validate event of htmx, which is called before the element's checkValidity() method is called. </p>
<p>Now, when we try to submit the form with a non-gmail.com address, we will see the same error message. </p>
<h2>What else can htmx do? </h2>
<p>htmx is a versatile, lightweight and easy to use tool. It successfully combines HTML simplicity with dynamic features often associated with complex JavaScript libraries, providing a compelling alternative to creating interactive web applications. </p>
<p> However, it is not a universal solution. For more complex applications, you may still need the JavaScript framework. But if your goal is to create fast, interactive and user-friendly web applications without adding too much complexity, htmx is definitely worth considering. </p>
<p>As web development continues to evolve, tools such as htmx provide exciting new ways to build a better user experience. Why not try it in future projects and see what htmx can do for you? </p>
<h2>FAQs about HTMX (FAQ)</h2>
<h3>What is HTMX and how is it different from other UI design tools? </h3>
<p>HTMX is a modern, lightweight HTML extension for AJAX, CSS transitions, WebSockets, and server sending events. It allows you to access modern browser features directly from HTML without JavaScript or JQuery. This makes it different from other UI design tools, which often rely heavily on JavaScript. HTMX is easy to integrate with any backend and does not require you to rewrite existing code. It is a powerful tool to enhance the user interface while keeping the code simple and easy to maintain. </p>
<h3>How to get started with HTMX? </h3>
<p>It's very easy to get started with HTMX. You just need to include the HTML script in the HTML file. Once you have done this, you can start using the HTMX properties in HTML tags to enable AJAX, WebSockets, and other features. The HTMX website provides comprehensive guides and examples to get you started. </p>
<h3>Can HTMX be used with any backend? </h3>
<p>Yes, one of the main advantages of HTMX is its backend-independent features. It can be used with any server-side language or framework. This makes it a universal tool for developers working in different environments. </p>
<h3>What are some common use cases for HTMX? </h3>
<p>HTMX can be used in a variety of scenarios where you want to enhance the user interface without relying on JavaScript. This includes form submission, real-time search, unlimited scrolling, real-time updates, and more. It is a powerful tool for creating dynamic, interactive web applications. </p>
<h3>How does HTMX handle CSS transitions? </h3>
<p>HTMX has built-in support for CSS transitions. You can use the "hx-swap" attribute to specify how elements should be swapped in and out when a request is made. This allows you to create smooth, visually appealing transitions without writing any JavaScript. </p>
<h3>Is HTMX compatible with all browsers? </h3>
<p>HTMX is designed to be compatible with all modern browsers. However, because it uses some newer browser features, it may not work perfectly in older or less common browsers. It is always recommended to test your application in browsers that users may use. </p>
<h3>How does HTMX improve the performance of web applications? </h3>
<p>HTMX can greatly reduce the amount of JavaScript you need to write by allowing you to access modern browser features directly from HTML. This can lead to faster load times and higher performance, especially on mobile devices, where JavaScript can be particularly slow on mobile devices. </p>
<h3>Can I use HTML and CSS with my existing HTML and CSS? </h3>
<p>Yes, HTML is designed to work with your existing HTML and CSS. You don't have to rewrite your code or learn a new language to get started with HTMX. This makes it an excellent choice for enhancing existing applications. </p>
<h3>What type of support does HTMX provide? </h3>
<p>HTMX is an open source project and has a vibrant developer community to use and contribute to it. You can find help and advice on the HTMX website, GitHub, and various online forums. </p>
<h3>How to contribute to HTMX projects? </h3>
<p>As an open source project, HTMX welcomes the community's contributions. You can contribute in a variety of ways, from reporting bugs and suggesting new features to writing code and improving documentation. Check out the HTMX GitHub page to learn how to get involved. </p>
</div>
The above is the detailed content of An Introduction to htmx, the HTML-focused Dynamic UI Library. For more information, please follow other related articles on the PHP Chinese website!