npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

skelkit

v1.1.1

Published

Zero-config automatic skeleton loading for any frontend. Just add data attributes and your UI gets beautiful shimmer placeholders.

Readme

SkelKit

Zero-config skeleton loading for any frontend. Add a data attribute, include one script — done. ✨

npm version license bundle size


Features

  • 🔥 Zero config — just add data-skelkit to your HTML elements
  • 🔗 Chainable APISkelKit.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 all

SkelKit.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 observer

SkelKit.isLoading(target) / SkelKit.refresh()

if (SkelKit.isLoading('#card')) { /* still loading */ }
SkelKit.refresh();  // re-scan DOM for new [data-skelkit] elements

Theming 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