How it works
Skeleton-auto runs at runtime — there is no build step, no fixture file, no Playwright job. It works in three phases:
- Render invisibly. When
loadingbecomes true, your real children are rendered withvisibility: hiddenandpointer-events: none, so the browser still computes layout but paints nothing. - Measure. The library walks the rendered tree (DOM on web, React element + ref tree on native), filters to leaf nodes, and reads their bounding rect. Each node is classified — text, image, circle, icon, rect — using a score-based role inferer.
- Overlay & animate. A skeleton layer is rendered above the children at the exact measured coordinates. Animation runs on the compositor (CSS keyframes on web) or the UI thread (Reanimated 3 on native) — never on JS.
Why measure at runtime?
Build-time approaches like Boneyard snapshot the DOM with Playwright in CI. That works once, but layouts drift the moment content changes. And there's no equivalent for React Native at all. Runtime measurement is ~1–3ms for a typical screen with ≤100 leaves — well below a frame budget — and stays correct as your UI evolves.
Role inference
Each leaf gets weighted scores across five roles. The highest score wins. Signals include: component type (Text vs Image vs View), aspect ratio, border radius, presence of text content, presence of background image, and an explicit data-skeleton-role attribute that always wins.
This is extensible — new signals are just additions to one scoring table.