Every time we build loading states in React, we usually end up doing something like this:
if (loading) return <UserProfileSkeleton />
return <UserProfile />
Now we have:
UserProfile
UserProfileSkeleton
- Two components.
- Two layouts.
- Two things to maintain.
And when the design changes?
You update both.
That’s duplicated UI logic.
The Real Problem
Skeleton screens are great for UX.
But maintaining them manually is painful.
- Layout changes → update skeleton
- Add a new field → update skeleton
- Adjust spacing → update skeleton
- Refactor component → update skeleton
It becomes repetitive and fragile.
What if we could generate skeleton screens automatically from the existing DOM structure?
Introducing AutoSkeleton
auto-skeleton-react lets you wrap any component and automatically generate a matching skeleton layout.
<AutoSkeleton loading={loading}>
<UserProfile />
AutoSkeleton>
That’s it.
- No separate skeleton component.
- No manual width/height tweaking.
- No duplicated layout structure.
It analyzes the rendered DOM and builds a skeleton that matches your existing layout.
For 70–80% of real-world use cases (dashboards, cards, forms, tables), this removes the need to build skeleton components manually.
Here’s what that looks like in practice:
🚀 Quick example
UserProfile component
export function UserProfile() {
return (
<div className="flex max-w-150 gap-4 p-5">
<Image
src="https://avatars.githubusercontent.com/u/58282436?v=4"
width={80}
height={80}
className="h-20 w-20 rounded-full"
alt="Avatar"
/>
<div className="flex-1">
<h2 className="m-0 mb-2 text-2xl">Shanuka Hettiarachchih2>
<p className="m-0 mb-3 text-[#666]">
Senior Software Engineer at Wire Apps
p>
<button className="cursor-pointer rounded-md border-none bg-blue-500 px-4 py-2 font-medium text-white">
Follow
button>
div>
div>
);
}
Now let’s wrap it using AutoSkeleton
<AutoSkeleton
loading={loading}
config={{
animation: "pulse",
baseColor: "#d4d4d8",
borderRadius: 8,
}}
>
<UserProfile />
AutoSkeleton>
🚀 Features
Zero manual skeleton components
Wrap any React component — no separate needed.
Layout preservation
Maintains flexbox, grid, margins, padding, and gaps to prevent layout shift.
Multi-line text detection
Automatically infers text line count from element height.
Table-aware rendering
Preserves semantic table structure (thead, tbody, tr, td) while skeletonizing content.
Selective opt-out
Use data-no-skeleton or .no-skeleton to keep specific elements visible during loading.
<button data-no-skeleton>Retrybutton>
Smooth transitions
Crossfades between skeleton and content for a natural UX.
Configurable
Control animation, colors, border radius, and depth limits.
⚠️ When NOT to Use It
AutoSkeleton uses DOM measurement, so it’s not ideal for:
- Extremely large or virtualized lists
- Highly dynamic layouts that constantly reflow
- Ultra SSR-sensitive pages where zero hydration shift is required
It’s designed primarily for dashboards, SaaS apps, admin panels, and structured UIs.
Why This Exists
The real pain isn’t “showing a loader”.
The real pain is:
Keeping loading UI in sync with real UI without writing everything twice.
AutoSkeleton tries to remove that duplication.
If this sounds useful, give it a try:
GitHub: https://github.com/ShanukJ/auto-skeleton
NPM: https://www.npmjs.com/package/auto-skeleton-react
Docs: https://autoskeleton.shanukj.me/docs
Demo: https://autoskeleton.shanukj.me/
I’d love to hear feedback — especially from production usage.

