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 Hettiarachchi</h2>
<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 <ComponentSkeleton /> 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>Retry</button>
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.


Top comments (0)