Skip to content
← Skeleton
Edit Skeleton
Name
Also known as (comma separated)
Brief definition
Placeholder representing loading content.
Notes
Tier
Core
Useful
Reference
Deleted
Controls schema (JSON array)
[ { "id": "label", "type": "text", "label": "Loading label", "default": "Loading content" }, { "id": "shape", "type": "select", "label": "Shape", "default": "text", "options": [ "text", "avatar", "card" ] }, { "id": "lines", "type": "number", "label": "Lines", "default": 3, "min": 1, "max": 6, "step": 1 }, { "id": "animated", "type": "toggle", "label": "Animated", "default": true } ]
Templates (JSON object keyed by format)
{ "html": "<div class=\"skeleton skeleton--{{shape}}{{#if animated}} skeleton--animated{{/if}}\" role=\"status\" aria-label=\"{{label}}\">\n {{#if animated}}<span class=\"skeleton__srtext\">{{label}}</span>{{/if}}\n <div class=\"skeleton__avatar\" aria-hidden=\"true\"></div>\n <div class=\"skeleton__lines\" aria-hidden=\"true\" style=\"--lines:{{lines}};\">\n <span class=\"skeleton__line\"></span><span class=\"skeleton__line\"></span><span class=\"skeleton__line\"></span>\n <span class=\"skeleton__line\"></span><span class=\"skeleton__line\"></span><span class=\"skeleton__line\"></span>\n </div>\n</div>\n<style>\n.skeleton { display: flex; align-items: flex-start; gap: 12px; width: 260px; }\n.skeleton__srtext { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }\n.skeleton__avatar { display: none; width: 44px; height: 44px; border-radius: 50%; background: #24143018; flex-shrink: 0; }\n.skeleton--avatar .skeleton__avatar { display: block; }\n.skeleton--card { flex-direction: column; }\n.skeleton--card .skeleton__avatar { display: block; width: 100%; height: 120px; border-radius: 10px; }\n.skeleton__lines { flex: 1; display: flex; flex-direction: column; gap: 8px; }\n.skeleton__line { display: none; height: 10px; border-radius: 5px; background: #24143018; }\n.skeleton__line:nth-child(1) { display: block; width: 100%; }\n.skeleton__lines[style*=\"--lines:2\"] .skeleton__line:nth-child(2),\n.skeleton__lines[style*=\"--lines:3\"] .skeleton__line:nth-child(2),\n.skeleton__lines[style*=\"--lines:4\"] .skeleton__line:nth-child(2),\n.skeleton__lines[style*=\"--lines:5\"] .skeleton__line:nth-child(2),\n.skeleton__lines[style*=\"--lines:6\"] .skeleton__line:nth-child(2) { display: block; width: 92%; }\n.skeleton__lines[style*=\"--lines:3\"] .skeleton__line:nth-child(3),\n.skeleton__lines[style*=\"--lines:4\"] .skeleton__line:nth-child(3),\n.skeleton__lines[style*=\"--lines:5\"] .skeleton__line:nth-child(3),\n.skeleton__lines[style*=\"--lines:6\"] .skeleton__line:nth-child(3) { display: block; width: 96%; }\n.skeleton__lines[style*=\"--lines:4\"] .skeleton__line:nth-child(4),\n.skeleton__lines[style*=\"--lines:5\"] .skeleton__line:nth-child(4),\n.skeleton__lines[style*=\"--lines:6\"] .skeleton__line:nth-child(4) { display: block; width: 88%; }\n.skeleton__lines[style*=\"--lines:5\"] .skeleton__line:nth-child(5),\n.skeleton__lines[style*=\"--lines:6\"] .skeleton__line:nth-child(5) { display: block; width: 94%; }\n.skeleton__lines[style*=\"--lines:6\"] .skeleton__line:nth-child(6) { display: block; width: 70%; }\n.skeleton--animated .skeleton__avatar, .skeleton--animated .skeleton__line {\n background: linear-gradient(90deg, #24143018 25%, #2414301f 37%, #24143018 63%); background-size: 400% 100%; }\n@keyframes skeleton-shimmer { 0% { background-position: 100% 0; } 100% { background-position: 0 0; } }\n@media (prefers-reduced-motion: no-preference) {\n .skeleton--animated .skeleton__avatar, .skeleton--animated .skeleton__line { animation: skeleton-shimmer .2s ease infinite; }\n}\n</style>", "tailwind": "<div role=\"status\" aria-label=\"{{label}}\" class=\"skeleton-tw skeleton-tw--{{shape}}{{#if animated}} skeleton-tw--animated{{/if}} flex items-start gap-3 w-64\">\n {{#if animated}}<span class=\"sr-only\">{{label}}</span>{{/if}}\n <div aria-hidden=\"true\" class=\"skeleton-tw__avatar hidden w-11 h-11 rounded-full bg-[#24143018] flex-shrink-0\"></div>\n <div aria-hidden=\"true\" class=\"skeleton-tw__lines flex-1 flex flex-col gap-2\" style=\"--lines:{{lines}};\">\n <span class=\"skeleton-tw__line block h-2.5 rounded-full bg-[#24143018] w-full\"></span>\n <span class=\"skeleton-tw__line h-2.5 rounded-full bg-[#24143018] w-[92%]\"></span>\n <span class=\"skeleton-tw__line h-2.5 rounded-full bg-[#24143018] w-[96%]\"></span>\n <span class=\"skeleton-tw__line h-2.5 rounded-full bg-[#24143018] w-[88%]\"></span>\n <span class=\"skeleton-tw__line h-2.5 rounded-full bg-[#24143018] w-[94%]\"></span>\n <span class=\"skeleton-tw__line h-2.5 rounded-full bg-[#24143018] w-[70%]\"></span>\n </div>\n</div>\n<style>\n.skeleton-tw--avatar .skeleton-tw__avatar { display: block; }\n.skeleton-tw--card { flex-direction: column; }\n.skeleton-tw--card .skeleton-tw__avatar { display: block; width: 100%; height: 120px; border-radius: 10px; }\n.skeleton-tw__lines > .skeleton-tw__line:nth-child(n+2) { display: none; }\n.skeleton-tw__lines[style*=\"--lines:2\"] > .skeleton-tw__line:nth-child(2),\n.skeleton-tw__lines[style*=\"--lines:3\"] > .skeleton-tw__line:nth-child(-n+3),\n.skeleton-tw__lines[style*=\"--lines:4\"] > .skeleton-tw__line:nth-child(-n+4),\n.skeleton-tw__lines[style*=\"--lines:5\"] > .skeleton-tw__line:nth-child(-n+5),\n.skeleton-tw__lines[style*=\"--lines:6\"] > .skeleton-tw__line:nth-child(-n+6) { display: block; }\n.skeleton-tw--animated .skeleton-tw__avatar, .skeleton-tw--animated .skeleton-tw__line {\n background: linear-gradient(90deg, #24143018 25%, #2414301f 37%, #24143018 63%); background-size: 400% 100%; }\n@keyframes skeleton-tw-shimmer { 0% { background-position: 100% 0; } 100% { background-position: 0 0; } }\n@media (prefers-reduced-motion: no-preference) {\n .skeleton-tw--animated .skeleton-tw__avatar, .skeleton-tw--animated .skeleton-tw__line { animation: skeleton-tw-shimmer .2s ease infinite; }\n}\n</style>", "react": "export function Skeleton({\n label = \"{{label}}\",\n shape = \"{{shape}}\",\n lines = {{lines}},\n animated = {{animated}},\n}) {\n const widths = [\"100%\", \"92%\", \"96%\", \"88%\", \"94%\", \"70%\"];\n const shimmer = animated\n ? { background: \"linear-gradient(90deg, #24143018 25%, #2414301f 37%, #24143018 63%)\", backgroundSize: \"400% 100%\" }\n : { background: \"#24143018\" };\n const shimmerClass = animated ? \"skel-shimmer\" : undefined;\n return (\n <div role=\"status\" aria-label={label} style={{ display: \"flex\", alignItems: shape === \"card\" ? \"stretch\" : \"flex-start\",\n flexDirection: shape === \"card\" ? \"column\" : \"row\", gap: 12, width: 260 }}>\n {animated && <span style={{ position: \"absolute\", width: 1, height: 1, overflow: \"hidden\", clip: \"rect(0 0 0 0)\" }}>{label}</span>}\n {shape !== \"text\" && (\n <div aria-hidden=\"true\" className={shimmerClass} style={{ width: shape === \"card\" ? \"100%\" : 44, height: shape === \"card\" ? 120 : 44,\n borderRadius: shape === \"card\" ? 10 : \"50%\", flexShrink: 0, ...shimmer }} />\n )}\n <div aria-hidden=\"true\" style={{ flex: 1, display: \"flex\", flexDirection: \"column\", gap: 8 }}>\n {widths.slice(0, lines).map((w, i) => (\n <span key={i} className={shimmerClass} style={{ height: 10, borderRadius: 5, width: w, ...shimmer }} />\n ))}\n </div>\n <style>{`\n @media (prefers-reduced-motion: no-preference) {\n .skel-shimmer { animation: skeleton-react-shimmer 1.4s ease infinite; }\n @keyframes skeleton-react-shimmer { 0% { background-position: 100% 0; } 100% { background-position: 0 0; } }\n }\n `}</style>\n </div>\n );\n}" }
Save
History