skelkit
v1.1.1
Published
Zero-config automatic skeleton loading for any frontend. Just add data attributes and your UI gets beautiful shimmer placeholders.
Maintainers
Readme
SkelKit
Zero-config skeleton loading for any frontend. Add a data attribute, include one script — done. ✨
Features
- 🔥 Zero config — just add
data-skelkitto your HTML elements - 🔗 Chainable API —
SkelKit.select('#el').circle('56px').pulse().show() - 🎨 4 animations — shimmer, pulse, wave, typing
- 🌈 Custom colors — per-element or global
- 🌗 Light & dark themes — built in
- 📦 Tiny footprint — ~3KB minified + gzipped
- 🧩 Any layout — rect, circle, text, card skeletons
- 👀 MutationObserver — auto-detects dynamically added elements
- 🚫 No dependencies — pure vanilla JavaScript
- 📋 UMD/ESM/CJS — works everywhere
Installation
npm
npm install skelkit// ES Module
import SkelKit from 'skelkit';
import 'skelkit/dist/skelkit.css';
// CommonJS
const SkelKit = require('skelkit');CDN (no build step)
<link rel="stylesheet" href="https://unpkg.com/skelkit/dist/skelkit.css">
<script src="https://unpkg.com/skelkit/dist/skelkit.umd.js"></script>Quick Start
Option A: HTML Attributes (zero-config)
<!-- Just add the data-skelkit attribute! -->
<div data-skelkit="rect" style="width: 200px; height: 20px;"></div>
<div data-skelkit="circle" style="width: 56px; height: 56px;"></div>
<script src="https://unpkg.com/skelkit/dist/skelkit.umd.js"></script>
<script>
// Skeletons auto-apply! Just reveal when data arrives:
fetch('/api/data').then(res => res.json()).then(data => {
SkelKit.revealAll();
});
</script>Option B: Chainable JavaScript API (recommended)
<div id="avatar"></div>
<div id="name"></div>
<div id="role"></div>
<script src="https://unpkg.com/skelkit/dist/skelkit.umd.js"></script>
<script>
// Clean, readable method chaining — no config objects!
SkelKit.select('#avatar').circle('56px').pulse().show();
SkelKit.select('#name').size('140px', '16px').radius('4px').show();
SkelKit.select('#role').size('90px', '12px').show();
// When data arrives (Success):
fetch('/api/user')
.then(res => {
if (!res.ok) throw new Error(res.status);
return res.json();
})
.then(user => {
document.getElementById('name').textContent = user.name;
SkelKit.select('#avatar').reveal();
SkelKit.select('#name').reveal();
SkelKit.select('#role').reveal();
})
.catch(err => {
// When data fails (Error / Offline):
if (err.message === '404') {
SkelKit.error404('#name-container', { title: 'User Not Found' });
} else {
SkelKit.offline('#name-container', {
bg: '#fee2e2', textColor: '#7f1d1d', iconColor: '#dc2626'
});
}
});
</script>🛑 State Views (Errors & Offline)
When an API request fails, don't leave the user hanging on a skeleton! SkelKit includes beautifully styled, built-in error states.
<div id="feed-container">
<!-- Initially starts as a skeleton... -->
<div data-skelkit="rect" style="height: 300px;"></div>
</div>
<script>
// Oops! We went offline. Let's transition the skeleton into an Offline message
SkelKit.offline('#feed-container', {
title: 'Connection Lost',
desc: 'We could not fetch your feed. Please check your network.',
buttonText: 'Try Again',
bg: '#1e1b4b', // (Optional) Override background color
textColor: '#c7d2fe', // (Optional) Override text color
iconColor: '#6366f1', // (Optional) Override icon color
buttonBg: '#4338ca', // (Optional) Override button background
buttonTextColor: '#fff', // (Optional) Override button text color
onAction: () => location.reload()
});
// Or maybe the resource wasn't found...
SkelKit.error404('#feed-container', {
title: 'Post Not Found',
desc: 'The content you are looking for has been deleted.',
buttonText: 'Go to Homepage',
onAction: () => window.location.href = '/'
});
</script>Data Attributes (HTML mode)
| Attribute | Values | Default | Description |
|---|---|---|---|
| data-skelkit | rect, circle, text, card, image, button | rect | Skeleton type |
| data-skelkit-animation | shimmer, pulse, wave, typing | shimmer | Animation style |
| data-skelkit-theme | light, dark | light | Color theme |
| data-skelkit-color | CSS color | auto | Custom background color |
| data-skelkit-shimmer | CSS color | auto | Custom shimmer highlight |
| data-skelkit-lines | number | 3 | Text lines (for text/card) |
| data-skelkit-width | CSS value | auto | Width override |
| data-skelkit-height | CSS value | auto | Height override |
| data-skelkit-radius | CSS value | 6px | Border radius |
| data-skelkit-count | number | 1 | Repeat skeleton N times |
| data-skelkit-delay | ms | 0 | Auto-reveal after delay |
Chainable API — SkelKit.select()
The easiest way to control skeletons from JavaScript. Every configuration method returns the builder so you can chain your setup.
Important: The skeleton is not applied to the DOM until you call .show(). This lets you store your skeleton configurations cleanly and execute them right when you need!
1. Direct Approach (Immediate)
// Sets up the configuration and immediately applies the placeholder
SkelKit.select('#my-element')
.circle('56px') // type + size shorthand
.color('#312e81', '#4338ca') // custom bg + shimmer color
.pulse() // animation shorthand
.show(); // ← applying the skeleton!2. Variable Storage Approach (Deferred)
// Define your skeleton style and store it in a variable
const avatarSkeleton = SkelKit.select('#avatar').circle('64px').pulse();
function loadData() {
// Trigger the skeleton right before the heavy loading begins
avatarSkeleton.show();
fetch('/api/user').then((data) => {
// When done, simply reveal it!
avatarSkeleton.reveal();
});
}Available chain methods
| Method | Description |
|---|---|
| .type(t) | Set type: 'rect', 'circle', 'text', 'card' |
| .rect() | Shorthand for rectangle |
| .circle(size?) | Shorthand for circle; if size given, sets width & height |
| .text(lines?) | Shorthand for text lines |
| .card(lines?) | Shorthand for card |
| .width(w) | Set CSS width |
| .height(h) | Set CSS height |
| .size(w, h?) | Set width and height at once |
| .radius(r) | Set border-radius |
| .shimmer() | Use shimmer animation |
| .pulse() | Use pulse animation |
| .wave() | Use wave animation |
| .typing() | Use typing animation (runs once) |
| .animation(a) | Set animation by name |
| .color(bg, shimmer?) | Set custom skeleton colors |
| .delay(ms) | Auto-reveal after delay |
| .auto() | Auto-detect size/shape and apply skeleton |
| .show() | Apply the skeleton |
| .isLoading() | Check if still loading |
| .error404(opts?) | Show inline 404 Not Found error state |
| .offline(opts?) | Show inline Offline error state |
📝 The Typing Effect
While shimmer, pulse, and wave are infinitely looping animations (they repeat forever), the typing animation is a special effect designed exclusively for text!
When you use .typing(), the gray text skeleton bars will literally grow from left-to-right progressively (one after another) imitating the look of text being typed onto the screen. It runs exactly once and then stays solid, avoiding excessive flashing and looping on your website.
// In Javascript: (great for subtitles or descriptions)
SkelKit.select('#description').text(3).typing().show();<!-- In HTML: -->
<div data-skelkit="text" data-skelkit-lines="3" data-skelkit-animation="typing"></div>Examples
// Avatar skeleton with pulse
SkelKit.select('#avatar').circle('64px').pulse().show();
// Text block with custom color
SkelKit.select('#bio').text(4).color('#1a1a2e', '#16213e').show();
// Card with wave animation, auto-reveals after 3 seconds
SkelKit.select('#card').card(3).wave().delay(3000).show();
// Later — reveal it
SkelKit.select('#avatar').reveal();Direct API
SkelKit.make(target, options)
Apply skeleton via an options object (alternative to chaining):
SkelKit.make('#avatar', {
type: 'circle',
width: '56px',
height: '56px',
animation: 'pulse',
color: '#312e81',
shimmerColor: '#4338ca',
});SkelKit.auto(target, options?)
Auto-detect an element's structural CSS (dimensions and border radius) and lay over a perfectly matched skeleton. Great for ensuring responsive placeholders correctly adapt.
// Just picks up the current size from the DOM!
SkelKit.auto('#user-avatar', { animation: 'wave' });
SkelKit.auto('.content-blocks');SkelKit.generate(target, children)
Inject multiple skeleton shapes inside a container:
SkelKit.generate('#card', [
{ type: 'rect', width: '100%', height: '120px', radius: '8px' },
{ type: 'rect', width: '70%', height: '16px', radius: '4px' },
{ type: 'rect', width: '55%', height: '12px', radius: '4px' },
]);SkelKit.setColor(bg, shimmer)
Change colors globally for all skeletons (current and future):
SkelKit.setColor('#1a1a2e', '#16213e');SkelKit.reveal(target) / SkelKit.revealAll()
SkelKit.reveal('#my-card'); // by selector
SkelKit.reveal(element); // by element
SkelKit.revealAll(); // remove allSkelKit.error404(target, options?) / SkelKit.offline(target, options?)
Replace a loading skeleton with an elegant inline error or offline state. Fully customizable text, icons, and colors.
// Fade out skeleton and show beautifully formatted 404
SkelKit.error404('#content', {
title: 'Entity Not Found',
desc: 'This item has been removed.',
buttonText: 'Homepage',
onAction: () => { window.location.href = '/'; }
});
// Configure colors specifically for the offline error state
SkelKit.offline('#feed', {
bg: '#1e1b4b',
textColor: '#c7d2fe',
iconColor: '#6366f1',
buttonBg: '#4338ca',
buttonTextColor: '#ffffff'
});SkelKit.init(config?) / SkelKit.destroy()
SkelKit.init({
animation: 'shimmer',
theme: 'light',
color: '#2d3748', // global skeleton color
shimmer: '#4a5568', // global shimmer color
autoInit: true,
observeDOM: true,
});
SkelKit.destroy(); // remove all + disconnect observerSkelKit.isLoading(target) / SkelKit.refresh()
if (SkelKit.isLoading('#card')) { /* still loading */ }
SkelKit.refresh(); // re-scan DOM for new [data-skelkit] elementsTheming with CSS Variables
:root {
--skelkit-bg: #e2e8f0; /* skeleton background */
--skelkit-shimmer: #f8fafc; /* shimmer highlight */
--skelkit-radius: 6px; /* border radius */
--skelkit-speed: 1.8s; /* animation speed */
--skelkit-line-height: 14px; /* text line height */
--skelkit-line-gap: 10px; /* gap between text lines */
}Browser Support
- Chrome 60+
- Firefox 55+
- Safari 12+
- Edge 79+
License
MIT © Divyanshu Gupta
- 🎨 3 animations — shimmer, pulse, wave
- 🌗 Light & dark themes — built in
- 📦 Tiny footprint — ~3KB minified + gzipped
- 🧩 Any layout — rect, circle, text, card skeletons
