Skip to content
    Style: Wireframe

    Components · Feedback

    Skeleton

    A loading placeholder with a slow sheen that stands still under reduced motion.

    Loading the team

    Both previews render the same markup; the HTML tab below is that markup without a framework.

    Install

    React
    npx shadcn@latest add https://www.themes.dev/ui/r/skeleton.json
    Astro
    npx shadcn@latest add https://www.themes.dev/ui/r/astro/skeleton.json

    Or copy the files below into your project. They need clsx, tailwind-merge, and the themes.dev UI theme. The HTML needs only the compiled CSS.

    skeleton.tsx
    import type { HTMLAttributes } from 'react';
    import { cn } from '@/lib/utils';
    import { skeletonClasses } from './skeleton.variants';
    
    export type SkeletonProps = HTMLAttributes<HTMLSpanElement>;
    
    /** A loading placeholder. Size it with classes (h-4 w-32, size-10 rounded-full); mark the region aria-busy. */
    export function Skeleton({ className, ...props }: SkeletonProps) {
      return <span aria-hidden="true" className={cn(skeletonClasses, className)} {...props} />;
    }
    skeleton.variants.ts
    /** A placeholder while content loads: a muted block with a slow sheen. With reduced motion it is a still block. Wrap them
     *  in role="status" aria-busy="true" with a visually hidden "Loading …"; the skeletons themselves are hidden. */
    export const skeletonClasses =
      'block rounded-md bg-muted bg-[linear-gradient(90deg,transparent,color-mix(in_oklab,var(--background)_55%,transparent),transparent)] bg-[length:200%_100%] bg-no-repeat animate-[caseroom-sheen_1.6s_ease-in-out_infinite] motion-reduce:animate-none';
    
    /** The keyframes, once in your CSS (the themes.dev UI theme has them). */
    export const SHEEN_KEYFRAMES = '@keyframes caseroom-sheen { from { background-position: 150% 0 } to { background-position: -50% 0 } }';