Skip to content

Skeleton Card Loader

Tailwind CSS skeleton loaders for an article card grid and a list, with pulse or shimmer animation that swaps to real content once loaded.

Live preview

Open in new tab

Code

Skeleton loaders for cards and lists built with Tailwind CSS and a few lines of vanilla JavaScript. Gray placeholder shapes mirror the final layout of an article grid and a contributor list, pulse while data is loading and are then swapped for the real content. Use them on blogs, dashboards and feeds to reduce layout shift and make loading feel faster than a spinner.

How it works

The root is .tsk-root. Inside it, the data-tsk-region wrapper holds two states: data-tsk-skeleton with the placeholders and data-tsk-content with the finished cards, which starts hidden. Each placeholder card is a .tsk-card with Tailwind's animate-pulse, and every shape inside it is a .tsk-bone: an aspect-video block for the image, rounded pills for tags, bars of different widths for the title and a circle for the avatar. The bones use the same spacing and sizes as the real article elements, so nothing jumps when content arrives.

On DOMContentLoaded the script calls load(), which shows the skeleton, sets aria-busy="true" and disables the Reload button (data-tsk-reload). After data-tsk-delay milliseconds showContent() hides the skeleton, reveals the content (which fades in through .tsk-fade) and announces the result. Clicking Reload runs the cycle again.

Customization

  • data-tsk-delay on .tsk-root: change the simulated loading time in milliseconds.
  • data-tsk-effect="shimmer" on .tsk-root: replace the pulse with a light sweep defined by tsk-shimmer in style.css.
  • bg-slate-200 on .tsk-bone: use bg-sky-100 or bg-zinc-300 for tinted or higher-contrast placeholders.
  • sm:grid-cols-2 lg:grid-cols-3 on both grids: change the column count, keeping skeleton and content in sync.
  • load() in script.js: replace the setTimeout with a fetch() call and build the cards before calling showContent().
  • Copy a .tsk-card block to add more placeholders, or delete the list card if you only need the grid.

Accessibility

The skeleton is decorative and marked aria-hidden="true", so screen readers never read out empty shapes. The region carries aria-busy while loading, and a visually hidden role="status" element announces "Loading articles" and "Articles loaded". The Reload button is disabled during loading and has a visible focus ring, as do the article links. Under prefers-reduced-motion: reduce the pulse, shimmer and fade-in are all turned off.

Usage notes

Without JavaScript the skeleton stays visible, so render the real content on the server when possible and use the skeleton only for client-side loading. For several instances on one page, give each .tsk-root its own heading id.

Requirements

Add these to your page (already included in the download):

  • <script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>

The Tailwind browser build is for prototyping. In production, compile Tailwind with its CLI or your bundler.

Skeleton Card Loader – Tailwind CSS skeleton loaders component screenshot
Skeleton Card Loader · Tailwind CSS Skeleton Loaders