A worked example, rendered from real sample data. Sign in to run the tool on your own input.
avatar
title
text
text
image
button.skeleton-container {
display: flex;
flex-direction: column;
gap: 12px;
padding: 16px;
}
.skeleton {
background: linear-gradient(90deg, #e5e7eb 25%, #f3f4f6 50%, #e5e7eb 75%);
background-size: 200% 100%;
border-radius: 6px;
animation: skeleton-shimmer 1.5s ease-in-out infinite;
}
@keyframes skeleton-shimmer {
from { background-position: 200% 0; }
to { background-position: -200% 0; }
}
.skeleton-1 { width: 48px; height: 48px; border-radius: 50%; }
.skeleton-2 { width: 60%; height: 20px; }
.skeleton-3 { width: 100%; height: 14px; }
.skeleton-4 { width: 100%; height: 14px; }
.skeleton-5 { width: 100%; height: 160px; }
.skeleton-6 { width: 120px; height: 36px; }
@media (prefers-reduced-motion: reduce) {
.skeleton { animation: none; background: #e5e7eb; }
}
/* A skeleton should mirror the real layout: same block count, same rough sizes, same order. */
/* Mismatched skeletons read as a second layout shift rather than a loading hint. */
/* HTML */
<div class="skeleton-container" role="status" aria-busy="true" aria-label="Loading content">
<div class="skeleton skeleton-1"></div>
<div class="skeleton skeleton-2"></div>
<div class="skeleton skeleton-3"></div>
<div class="skeleton skeleton-4"></div>
<div class="skeleton skeleton-5"></div>
<div class="skeleton skeleton-6"></div>
</div>
Generate shimmer skeleton placeholder CSS for loading states. Part of the DevTools Surf developer suite. Browse more tools in the Animation / CSS collection.