UNPKG

htmx-ext-skeleton

Version:

An htmx extension for displaying skeleton screens during AJAX requests

185 lines (138 loc) 4.77 kB
# htmx-ext-skeleton An htmx extension for displaying skeleton screens during requests. ## Installation ### Via CDN ```html <script src="https://unpkg.com/htmx.org"></script> <script src="https://unpkg.com/htmx-ext-skeleton"></script> ``` ### Via npm ```bash npm install htmx-ext-skeleton ``` Then import in your JavaScript: ```javascript import 'htmx.org'; import 'htmx-ext-skeleton'; ``` ## Usage ### Basic Usage (Default Skeleton) 1. Define a skeleton template with `id="skeleton"`: ```html <script type="text/template" id="skeleton"> <div class="skeleton-placeholder"> <div class="skeleton-line"></div> <div class="skeleton-line"></div> <div class="skeleton-line"></div> </div> </script> ``` 2. Add `hx-ext="skeleton"` to your htmx element: ```html <div hx-ext="skeleton" hx-get="/api/data" hx-target="#content"> Load Data </div> <div id="content"> <!-- Initial content here --> </div> ``` ### Custom Skeleton (Optional) If you need multiple different skeletons, specify a custom template using any CSS selector: ```html <script type="text/template" id="custom-skeleton"> <div class="custom-loading">...</div> </script> <div hx-ext="skeleton" hx-get="/api/data" hx-target="#content" hx-skeleton="#custom-skeleton"> Load Data </div> ``` ### Custom Skeleton Target (Optional) Use `hx-skeleton-target` to display the skeleton in a different element than the swap target: ```html <button hx-ext="skeleton" hx-get="/api/data" hx-target="#results" hx-skeleton-target="#loading-area"> Load Data </button> <div id="loading-area"> <!-- Skeleton appears here --> </div> <div id="results"> <!-- Data swaps here --> </div> ``` If `hx-skeleton-target` is not specified, the extension falls back to `hx-target`, and if that's not present, it uses htmx's default target (the element itself). ### Alpine.js Integration (Optional) If Alpine.js is detected, you can override and extend data in your skeleton template using `hx-skeleton-alpine`: ```html <script type="text/template" id="skeleton"> <div x-data="{ title: 'Loading...', count: 3 }"> <h3 x-text="title"></h3> <template x-for="i in count" :key="i"> <div class="skeleton-item"></div> </template> </div> </script> <div hx-ext="skeleton" hx-get="/api/data" hx-target="#content" hx-skeleton-alpine='{"title": "Loading Projects", "count": 5}'> Load Data </div> ``` ## Features - **Zero configuration**: Just add `hx-ext="skeleton"` and create a template with `id="skeleton"` - **Instant feedback**: Shows skeleton immediately when request starts - **Automatic cleanup**: Removes skeleton when new content arrives - **Error handling**: Restores original content if request fails - **History support**: Properly handles browser back/forward navigation - **Multiple skeletons**: Use `hx-skeleton` with any CSS selector for custom templates - **Custom targets**: Use `hx-skeleton-target` to display skeleton in a different element than the swap target - **Alpine.js support**: Optional integration with Alpine.js for dynamic skeleton templates ## How it works 1. When an htmx request starts (`htmx:beforeRequest`), the extension: - Saves the original content - Replaces it with the skeleton template - Adds a `skeleton-loading` class 2. When the response arrives (`htmx:beforeSwap`), the extension: - Removes the `skeleton-loading` class - Allows htmx to swap in the new content 3. If an error occurs, the extension: - Restores the original content - Removes the `skeleton-loading` class ## Styling Add CSS to style your skeleton screens: ```css .skeleton-loading { pointer-events: none; opacity: 0.7; } .skeleton-line { height: 1rem; background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%); background-size: 200% 100%; animation: skeleton-loading 1.5s ease-in-out infinite; margin-bottom: 0.5rem; border-radius: 4px; } @keyframes skeleton-loading { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } } ``` ## Changelog ### 0.2.0 (2025-10-04) - **Breaking/Enhancement**: `hx-skeleton` now accepts any CSS selector instead of just an ID (defaults to `#skeleton` for backward compatibility) - **New Feature**: Added `hx-skeleton-target` attribute to specify a different target for skeleton display - **Enhancement**: Improved target resolution - falls back to `hx-target`, then htmx default if `hx-skeleton-target` not specified ### 0.1.1 - Fixed issue that could cause skeleton to re-appear when navigating back in browser - Added tests - Updated Alpine.js integration to require x-data initialization within skeleton template - Added optional Alpine.js support to skeleton templates ## License MIT