Loading skeleton
Source: kaleidoscope/src/demos/loading-skeleton.tsx Category: Animation
Loading skeleton — placeholder rectangles shaped like the content that’s loading. A shimmer animation signals “still working” without the jarring binary of “spinner → content”. Users perceive the page as loading faster than with a spinner even when the actual time is identical.
function Skeleton({ width = '100%', height = 14 }) { return ( <div style={{ width, height, borderRadius: 4, overflow: 'hidden', position: 'relative', background: '#1e293b' }}> <div className="shimmer" /> </div> );}
// CSS.shimmer { position: absolute; inset: 0; width: 40%; background: linear-gradient(90deg, transparent, rgba(255,255,255,0.08), transparent); animation: shimmer 1.6s linear infinite;}@keyframes shimmer { to { transform: translateX(350%); } }When it pays off
Section titled “When it pays off”- Initial page loads where layout is predictable (card grid, list view)
- Stream-in content (chat, comments) where the user can start reading shortly before all data arrives
- Long-loading media (image grids, video thumbnails) where the final shape is known
When it doesn’t
Section titled “When it doesn’t”- Error states. If the load fails, skeletons keep shimmering forever. Timeout + retry UI.
- Infinite variance in content shape. A chat with messages of wildly different lengths looks silly with uniform skeletons.
- Very short loads (under 300ms). Skeletons flash in and out; just show the real content when it arrives.
Gotchas
Section titled “Gotchas”- Match the real layout. Skeleton and loaded content should occupy the same dimensions. Otherwise content shift happens when the load completes — worse than no skeleton.
- Don’t animate too fast. Shimmer speed between 1.2-2s per cycle is comfortable. Faster feels anxious; slower feels stalled.
- Respect
prefers-reduced-motion. Render the gray shapes without shimmer; static skeleton is fine. will-change: transformon the shimmer element helps GPU composition. Especially useful on mobile.- Keys on dynamic lists. If you render N skeletons and then N real items, use stable keys so React reconciles correctly and transitions don’t flash.
- Terminal version. Ink version uses
░▒block characters in a wave pattern. No opacity, no transforms — just re-render characters per frame. See kaleidoscope source.
See also
Section titled “See also”- components/thinking-indicator — sibling motif for unknown-shape content
- components/progress-bar-subpixel — when you actually know the progress