Skeleton Loading

Component

Free, copy-pasteable Tailwind CSS Skeleton Loading component. Accessible, fully responsive, dark-mode ready, and customizable.

Install via CLI

Run this command to automatically add the component and its dependencies to your project.

npx @abhaysinghr516/business-wish add skeleton
New to the CLI? Run npx @abhaysinghr516/business-wish init first to initialize your project.

When data is fetching, a Tailwind skeleton loader prevents layout shift and keeps users engaged. These Tailwind CSS loading skeleton components mimic your actual content's shape perfectly, offering a seamless perceived performance boost with smooth shimmer animations.

Pair a skeleton with complex layouts like a Card or Avatar, or use a standard indeterminate Loader for smaller inline actions.

Basic Skeleton

import React from "react";

const Skeleton = () => {
  return (
    <div className="max-w-3xl mx-auto p-8 bg-white dark:bg-[#0A0A0A] rounded-[24px] shadow-sm border border-neutral-200/60 dark:border-white/10">
      <div className="space-y-6">
        <div className="space-y-4 animate-pulse">
          <div className="flex space-x-3">
            <div className="h-3 bg-neutral-100 dark:bg-neutral-800/80 rounded-full w-24"></div>
            <div className="h-3 bg-neutral-100 dark:bg-neutral-800/80 rounded-full w-16"></div>
            <div className="h-3 bg-neutral-100 dark:bg-neutral-800/80 rounded-full w-20"></div>
          </div>
          <div className="space-y-3">
            <div className="h-4 bg-neutral-100 dark:bg-neutral-800/80 rounded-full w-3/4"></div>
            <div className="h-4 bg-neutral-100 dark:bg-neutral-800/80 rounded-full w-full"></div>
            <div className="h-4 bg-neutral-100 dark:bg-neutral-800/80 rounded-full w-2/3"></div>
          </div>
          <div className="space-y-3 pt-4">
            <div className="h-3 bg-neutral-100 dark:bg-neutral-800/80 rounded-full w-full"></div>
            <div className="h-3 bg-neutral-100 dark:bg-neutral-800/80 rounded-full w-5/6"></div>
            <div className="h-3 bg-neutral-100 dark:bg-neutral-800/80 rounded-full w-3/4"></div>
          </div>
        </div>
      </div>
    </div>
  );
};

export default Skeleton;

Skeleton Loading for Image Card

import React from "react";

const Skeleton = () => {
  return (
    <div className="max-w-md mx-auto overflow-hidden bg-white dark:bg-[#0A0A0A] rounded-[24px] shadow-sm border border-neutral-200/60 dark:border-white/10">
      <div className="animate-pulse">
        <div className="h-52 bg-neutral-100 dark:bg-neutral-800/80"></div>
        <div className="p-6 space-y-4">
          <div className="h-5 bg-neutral-100 dark:bg-neutral-800/80 rounded-full w-2/3"></div>
          <div className="space-y-2.5 pt-2">
            <div className="h-3 bg-neutral-100 dark:bg-neutral-800/80 rounded-full w-full"></div>
            <div className="h-3 bg-neutral-100 dark:bg-neutral-800/80 rounded-full w-5/6"></div>
          </div>
          <div className="flex justify-between pt-6">
            <div className="h-9 bg-neutral-100 dark:bg-neutral-800/80 rounded-xl w-28"></div>
            <div className="h-9 bg-neutral-100 dark:bg-neutral-800/80 rounded-xl w-20"></div>
          </div>
        </div>
      </div>
    </div>
  );
};

export default Skeleton;

Skeleton Loading for User Profile

import React from "react";

const Skeleton = () => {
  return (
    <div className="max-w-md mx-auto p-6 bg-white dark:bg-[#0A0A0A] rounded-[28px] shadow-[0_8px_30px_rgb(0,0,0,0.04)] dark:shadow-[0_8px_30px_rgb(0,0,0,0.1)] border border-neutral-200/60 dark:border-white/10">
      <div className="animate-pulse">
        <div className="flex items-center space-x-4">
          <div className="relative flex-shrink-0">
            <div className="w-16 h-16 bg-neutral-100 dark:bg-neutral-800/80 rounded-full"></div>
            <div className="absolute bottom-0 right-0 w-4 h-4 bg-neutral-200 dark:bg-neutral-700 rounded-full border-2 border-white dark:border-[#0A0A0A]"></div>
          </div>
          <div className="flex-1 min-w-0">
            <div className="h-4 bg-neutral-100 dark:bg-neutral-800/80 rounded-full w-32 mb-3"></div>
            <div className="h-3 bg-neutral-100 dark:bg-neutral-800/80 rounded-full w-24"></div>
          </div>
          <div className="h-9 bg-neutral-100 dark:bg-neutral-800/80 rounded-full w-20"></div>
        </div>
        <div className="mt-8 space-y-3">
          <div className="h-3 bg-neutral-100 dark:bg-neutral-800/80 rounded-full w-full"></div>
          <div className="h-3 bg-neutral-100 dark:bg-neutral-800/80 rounded-full w-5/6"></div>
        </div>
        <div className="mt-8 grid grid-cols-3 gap-3">
          {[1, 2, 3].map((i) => (
            <div
              key={i}
              className="h-24 bg-neutral-100 dark:bg-neutral-800/80 rounded-[20px]"
            ></div>
          ))}
        </div>
      </div>
    </div>
  );
};

export default Skeleton;

Skeleton with Loaded Content

import React from "react";

const Skeleton = () => {
  return (
    <div className="max-w-3xl mx-auto p-6">
      <style jsx>{`
        @keyframes shimmer {
          100% {
            transform: translateX(100%);
          }
        }
        .shimmer-wrapper {
          position: relative;
          overflow: hidden;
        }
        .shimmer-wrapper::after {
          position: absolute;
          top: 0;
          right: 0;
          bottom: 0;
          left: 0;
          transform: translateX(-100%);
          background-image: linear-gradient(
            90deg,
            rgba(255, 255, 255, 0) 0,
            rgba(255, 255, 255, 0.4) 20%,
            rgba(255, 255, 255, 0.6) 60%,
            rgba(255, 255, 255, 0)
          );
          animation: shimmer 2s infinite;
          content: "";
        }
        .dark .shimmer-wrapper::after {
          background-image: linear-gradient(
            90deg,
            rgba(255, 255, 255, 0) 0,
            rgba(255, 255, 255, 0.05) 20%,
            rgba(255, 255, 255, 0.08) 60%,
            rgba(255, 255, 255, 0)
          );
        }
      `}</style>
      <div className="bg-white dark:bg-[#0A0A0A] rounded-[24px] shadow-sm border border-neutral-200/60 dark:border-white/10 overflow-hidden">
        <div className="p-6 shimmer-wrapper bg-neutral-50/50 dark:bg-neutral-900/20">
          <div className="flex items-center space-x-4 mb-8">
            <div className="w-14 h-14 bg-neutral-200/80 dark:bg-neutral-800 rounded-full"></div>
            <div className="flex-1">
              <div className="h-4 bg-neutral-200/80 dark:bg-neutral-800 rounded-full w-40 mb-3"></div>
              <div className="h-3 bg-neutral-200/80 dark:bg-neutral-800 rounded-full w-24"></div>
            </div>
            <div className="h-9 bg-neutral-200/80 dark:bg-neutral-800 rounded-xl w-24"></div>
          </div>
          <div className="space-y-3 mb-8">
            <div className="h-3 bg-neutral-200/80 dark:bg-neutral-800 rounded-full w-full"></div>
            <div className="h-3 bg-neutral-200/80 dark:bg-neutral-800 rounded-full w-5/6"></div>
            <div className="h-3 bg-neutral-200/80 dark:bg-neutral-800 rounded-full w-4/6"></div>
          </div>
          <div className="grid grid-cols-4 gap-4">
            {[1, 2, 3, 4].map((i) => (
              <div
                key={i}
                className="h-20 bg-neutral-200/80 dark:bg-neutral-800 rounded-[16px]"
              ></div>
            ))}
          </div>
        </div>
        <div className="p-8 border-t border-neutral-200/60 dark:border-white/10">
          <h2 className="text-xl font-semibold text-neutral-900 dark:text-white mb-3 tracking-tight">
            Your Content
          </h2>
          <p className="text-[15px] text-neutral-600 dark:text-neutral-400 leading-relaxed max-w-2xl">
            Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do
            eiusmod tempor incididunt ut labore et dolore magna aliqua.
          </p>
        </div>
      </div>
    </div>
  );
};

export default Skeleton;

Minimalist Table Skeleton

import React from "react";

const Skeleton = () => {
  return (
    <div className="max-w-4xl mx-auto w-full bg-white dark:bg-[#0A0A0A] rounded-[24px] shadow-sm border border-neutral-200/60 dark:border-white/10 overflow-hidden">
      <div className="px-6 py-5 border-b border-neutral-200/60 dark:border-white/10 flex items-center justify-between">
        <div className="h-5 bg-neutral-100 dark:bg-neutral-800/80 rounded-full w-32 animate-pulse"></div>
        <div className="h-8 bg-neutral-100 dark:bg-neutral-800/80 rounded-lg w-24 animate-pulse"></div>
      </div>
      <div className="overflow-x-auto">
        <table className="w-full">
          <thead>
            <tr className="border-b border-neutral-200/60 dark:border-white/5 bg-neutral-50/50 dark:bg-neutral-900/20">
              {[1, 2, 3, 4].map((i) => (
                <th key={`th-${i}`} className="px-6 py-4 text-left">
                  <div className="h-3 bg-neutral-200 dark:bg-neutral-800 rounded-full w-20 animate-pulse"></div>
                </th>
              ))}
            </tr>
          </thead>
          <tbody className="divide-y divide-neutral-200/40 dark:divide-white/5">
            {[1, 2, 3, 4, 5].map((row) => (
              <tr key={`tr-${row}`}>
                <td className="px-6 py-4">
                  <div className="flex items-center gap-3">
                    <div className="w-8 h-8 rounded-full bg-neutral-100 dark:bg-neutral-800/80 animate-pulse"></div>
                    <div className="h-4 bg-neutral-100 dark:bg-neutral-800/80 rounded-full w-32 animate-pulse"></div>
                  </div>
                </td>
                <td className="px-6 py-4">
                  <div className="h-4 bg-neutral-100 dark:bg-neutral-800/80 rounded-full w-24 animate-pulse"></div>
                </td>
                <td className="px-6 py-4">
                  <div className="h-4 bg-neutral-100 dark:bg-neutral-800/80 rounded-full w-16 animate-pulse"></div>
                </td>
                <td className="px-6 py-4">
                  <div className="h-8 bg-neutral-100 dark:bg-neutral-800/80 rounded-lg w-20 animate-pulse"></div>
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </div>
  );
};

export default Skeleton;

Dashboard Widget Skeleton

import React from "react";

const Skeleton = () => {
  return (
    <div className="max-w-sm w-full mx-auto p-6 bg-white dark:bg-[#0A0A0A] rounded-[28px] shadow-sm border border-neutral-200/60 dark:border-white/10">
      <div className="animate-pulse">
        <div className="flex items-center justify-between mb-8">
          <div>
            <div className="h-3 bg-neutral-100 dark:bg-neutral-800/80 rounded-full w-20 mb-3"></div>
            <div className="h-6 bg-neutral-100 dark:bg-neutral-800/80 rounded-full w-32"></div>
          </div>
          <div className="w-10 h-10 bg-neutral-100 dark:bg-neutral-800/80 rounded-xl"></div>
        </div>
        
        <div className="flex justify-center mb-8">
          <div className="relative w-40 h-40">
            <div className="absolute inset-0 rounded-full border-[12px] border-neutral-100 dark:border-neutral-800/80 opacity-60"></div>
            <div className="absolute inset-0 rounded-full border-[12px] border-neutral-200 dark:border-neutral-700/80 border-t-transparent border-r-transparent rotate-45"></div>
            <div className="absolute inset-0 flex items-center justify-center flex-col">
              <div className="h-5 bg-neutral-200 dark:bg-neutral-700 rounded-full w-16 mb-2"></div>
              <div className="h-3 bg-neutral-100 dark:bg-neutral-800/80 rounded-full w-10"></div>
            </div>
          </div>
        </div>

        <div className="space-y-4">
          {[1, 2, 3].map((i) => (
            <div key={i} className="flex items-center justify-between">
              <div className="flex items-center gap-3">
                <div className="w-3 h-3 rounded-full bg-neutral-200 dark:bg-neutral-700"></div>
                <div className="h-3 bg-neutral-100 dark:bg-neutral-800/80 rounded-full w-24"></div>
              </div>
              <div className="h-3 bg-neutral-100 dark:bg-neutral-800/80 rounded-full w-12"></div>
            </div>
          ))}
        </div>
      </div>
    </div>
  );
};

export default Skeleton;