How It Works
AutoSkeleton generates loading skeletons automatically by inspecting your rendered DOM. No manual skeleton components needed.
The Pipeline
┌─────────┐ ┌─────────┐ ┌──────────┐ ┌───────────┐ ┌──────────┐│ Render │ -> │ Measure │ -> │ Infer │ -> │ Blueprint │ -> │ Render ││ (hidden) │ │ (DOM) │ │ (roles) │ │ (tree) │ │(skeleton)│└─────────┘ └─────────┘ └──────────┘ └───────────┘ └──────────┘Step 1: Hidden Render
When loading={true}, your children are rendered in a hidden measurement container (opacity: 0, position: absolute). This allows the browser to compute layout without showing content.
Step 2: DOM Measurement
Using requestAnimationFrame to ensure paint is complete, the library traverses the DOM tree:
- Calls
getBoundingClientRect()on every element - Reads
getComputedStyle()for display, flex, grid, font, and spacing properties - Records tag names, attributes, and text content
- Respects
maxDepthlimit (default: 10 levels)
Step 3: Role Inference
Each leaf element is classified using a score-based heuristic system:
| Role | Key Signals |
|---|---|
| text | Has text content, text-range height, typical text tags |
| image | <img> tag, role="img", background-image |
| icon | <svg> tag, small and square |
| button | <button> tag, role="button", cursor: pointer |
| input | <input>, <textarea>, <select>, contenteditable |
The highest-scoring role wins. Minimum threshold is 30 points.
Step 4: Blueprint Generation
A tree of SkeletonNode objects is built:
- Containers preserve layout (display, flex, grid, gaps, padding)
- Leaf elements become skeleton blocks (sized to match the original)
- Multi-line text is detected via
height / line-heightand rendered as multiple bars - Tables preserve their structural HTML (thead, tbody, tr, th, td)
Step 5: Skeleton Rendering
The skeleton is rendered as an absolute-positioned overlay on top of the hidden content:
┌──────────────────────────┐│ Wrapper (position: rel) ││ ┌────────────────────┐ ││ │ Content (hidden) │ │ <- visibility: hidden during loading│ └────────────────────┘ ││ ┌────────────────────┐ ││ │ Skeleton (overlay) │ │ <- position: absolute, z-index on top│ └────────────────────┘ ││ ┌────────────────────┐ ││ │ Measure (hidden) │ │ <- opacity: 0, for DOM measurement│ └────────────────────┘ │└──────────────────────────┘Transitions
When loading changes from true to false:
- Content becomes visible
- Skeleton fades out over 300ms (
opacity: 1 -> 0) - After fade completes, skeleton is unmounted
This produces a smooth crossfade between skeleton and real content.
Key Design Decisions
- Leaf-only replacement: Containers keep their real layout. Only visual leaf elements (text, images, buttons) become skeleton blocks.
- Overlay approach: Content is always in the DOM (just hidden), preventing layout shifts when content appears.
- Client-side only: Measurement requires a real DOM, so skeletons are generated at runtime (not at build time or on the server).
Next Steps
- API Reference - Full props and types documentation
- Architecture Deep Dive - Scoring heuristics, multi-line detection, and more