|$ curl https://forge-ai.dev/api/markdown?path=docs/components/skeleton
$cat docs/skeleton-loaders.md
updated Recently·18 min read·published

Skeleton Loaders

CSSHTMLTailwindBootstrapUIIntermediate🎯Free Tools
Introduction

Skeleton loaders are empty placeholders that mirror the final layout while content loads. This guide covers production-ready skeleton patterns in plain HTML/CSS, Tailwind CSS, and Bootstrap — including text, avatars, cards, tables, media, forms, stats, and accessibility.

info

Match the skeleton shape to the real content as closely as possible. When the layout does not change after data arrives, the transition feels instant rather than jarring.
Text Skeleton

Paragraph-shaped skeleton lines with varying widths to mimic natural text wrapping.

text-skeleton
Live
untitled.html
HTML
1<div class="wrap">
2 <div class="sk-line w100">
3 </div>
4 <div class="sk-line w95">
5 </div>
6 <div class="sk-line w80">
7 </div>
8 <div class="sk-line w60">
9 </div>
10</div>
preview

info

Make the last line shorter than the others (60-70% width) to mimic natural text wrapping. This small detail makes the skeleton feel much more realistic than uniform-width lines.
Avatar + Text

Skeleton for a user row with circular avatar placeholder and text lines — common in feeds and lists.

avatar-text-skeleton
Live
untitled.html
HTML
1<div class="list">
2 <div class="row">
3 <div class="sk-circle">
4 </div>
5 <div class="lines">
6 <div class="sk-line w40">
7 </div>
8 <div class="sk-line w70">
9 </div>
10 </div>
11 </div>
12 <div class="row">
13 <div class="sk-circle">
14 </div>
15 <div class="lines">
16 <div class="sk-line w35">
17 </div>
18 <div class="sk-line w60">
19 </div>
20 </div>
21 </div>
22 <div class="row">
23 <div class="sk-circle">
24 </div>
25 <div class="lines">
26 <div class="sk-line w50">
27 </div>
28 <div class="sk-line w80">
29 </div>
30 </div>
31 </div>
32 <div class="row">
33 <div class="sk-circle">
34 </div>
35 <div class="lines">
36 <div class="sk-line w30">
37 </div>
38 <div class="sk-line w55">
39 </div>
40 </div>
41 </div>
42</div>
preview
Card Skeleton

Skeleton placeholder for a content card with image area, title, text lines, and action buttons.

card-skeleton
Live
untitled.html
HTML
1<div class="card-sk">
2 <div class="sk-img">
3 </div>
4 <div class="card-body">
5 <div class="sk-line w60 title">
6 </div>
7 <div class="sk-line w100">
8 </div>
9 <div class="sk-line w90">
10 </div>
11 <div class="sk-line w75">
12 </div>
13 <div class="actions">
14 <div class="sk-btn">
15 </div>
16 <div class="sk-btn">
17 </div>
18 </div>
19 </div>
20</div>
preview

best practice

Match the skeleton shape to the actual content layout. If your card has an image on the left, don't show a full-width image skeleton. The closer the skeleton matches the final layout, the less jarring the transition.
Image & Media Grid

A responsive grid of media placeholders for galleries, video thumbnails, or product images.

image-media-skeleton
Live
untitled.html
HTML
1<div class="gallery">
2 <div class="sk-img">
3 </div>
4 <div class="sk-img">
5 </div>
6 <div class="sk-img">
7 </div>
8 <div class="sk-img">
9 </div>
10</div>
preview
Form Inputs

Skeleton labels and input fields for login, checkout, or settings forms while fields initialize.

form-skeleton
Live
untitled.html
HTML
1<div class="form-sk">
2 <div class="field">
3 <div class="sk-label w30">
4 </div>
5 <div class="sk-input w100">
6 </div>
7 </div>
8 <div class="field">
9 <div class="sk-label w30">
10 </div>
11 <div class="sk-input w100">
12 </div>
13 </div>
14 <div class="field">
15 <div class="sk-label w30">
16 </div>
17 <div class="sk-input w100">
18 </div>
19 </div>
20 <div class="sk-btn">
21 </div>
22</div>
preview
📝

note

Form skeletons should preserve label-to-field spacing and input heights. If real inputs use helper text or error messages, leave room for those regions so the form does not jump when validation messages appear.
Table Skeleton

Skeleton rows and columns mimicking a data table while content loads from the server.

table-skeleton
Live
untitled.html
HTML
1<div class="table-sk">
2 <div class="sk-header">
3 <div class="sk-cell w20">
4 </div>
5 <div class="sk-cell w30">
6 </div>
7 <div class="sk-cell w25">
8 </div>
9 <div class="sk-cell w15">
10 </div>
11 </div>
12 <div class="sk-row">
13 <div class="sk-cell w20">
14 </div>
15 <div class="sk-cell w30">
16 </div>
17 <div class="sk-cell w25">
18 </div>
19 <div class="sk-cell w15">
20 </div>
21 </div>
22 <div class="sk-row">
23 <div class="sk-cell w20">
24 </div>
25 <div class="sk-cell w30">
26 </div>
27 <div class="sk-cell w25">
28 </div>
29 <div class="sk-cell w15">
30 </div>
31 </div>
32 <div class="sk-row">
33 <div class="sk-cell w20">
34 </div>
35 <div class="sk-cell w30">
36 </div>
37 <div class="sk-cell w25">
38 </div>
39 <div class="sk-cell w15">
40 </div>
41 </div>
42 <div class="sk-row">
43 <div class="sk-cell w20">
44 </div>
45 <div class="sk-cell w30">
46 </div>
47 <div class="sk-cell w25">
48 </div>
49 <div class="sk-cell w15">
50 </div>
51 </div>
52</div>
preview
Dashboard Stats

Metric cards for dashboards — labels, large values, and micro-trends rendered as skeleton blocks.

stats-skeleton
Live
untitled.html
HTML
1<div class="stats">
2 <div class="stat-card">
3 <div class="sk-line w40">
4 </div>
5 <div class="sk-num w60">
6 </div>
7 <div class="sk-line w80">
8 </div>
9 </div>
10 <div class="stat-card">
11 <div class="sk-line w40">
12 </div>
13 <div class="sk-num w50">
14 </div>
15 <div class="sk-line w70">
16 </div>
17 </div>
18 <div class="stat-card">
19 <div class="sk-line w40">
20 </div>
21 <div class="sk-num w70">
22 </div>
23 <div class="sk-line w60">
24 </div>
25 </div>
26</div>
preview
Custom Shapes

Skeleton elements for buttons, badges, thumbnails, and circular shapes — build any layout.

shape-skeleton
Live
untitled.html
HTML
1<div class="wrap">
2 <div class="sk-circle lg">
3 </div>
4 <div class="sk-circle md">
5 </div>
6 <div class="sk-circle sm">
7 </div>
8 <div class="sk-rect">
9 </div>
10 <div class="sk-pill">
11 </div>
12 <div class="sk-btn-sk">
13 </div>
14</div>
preview
Code Block

A terminal-style skeleton for documentation, logs, or snippet loaders with indented lines.

code-skeleton
Live
untitled.html
HTML
1<div class="code-sk">
2 <div class="sk-line">
3 </div>
4 <div class="sk-line indent">
5 </div>
6 <div class="sk-line indent">
7 </div>
8 <div class="sk-line">
9 </div>
10 <div class="sk-line indent">
11 </div>
12</div>
preview
Staggered Animation

Skeleton lines with staggered animation delays create a cascading shimmer effect that feels more natural.

staggered-skeleton
Live
untitled.html
HTML
1<div class="wrap">
2 <div class="row">
3 <div class="sk-circle">
4 </div>
5 <div class="lines">
6 <div class="sk-line w50 d1">
7 </div>
8 <div class="sk-line w80 d2">
9 </div>
10 </div>
11 </div>
12 <div class="row">
13 <div class="sk-circle d1">
14 </div>
15 <div class="lines">
16 <div class="sk-line w60 d2">
17 </div>
18 <div class="sk-line w45 d3">
19 </div>
20 </div>
21 </div>
22 <div class="row">
23 <div class="sk-circle d2">
24 </div>
25 <div class="lines">
26 <div class="sk-line w40 d3">
27 </div>
28 <div class="sk-line w70 d4">
29 </div>
30 </div>
31 </div>
32</div>
preview
🔥

pro tip

Add staggered animation-delay values (0.1s increments) to each skeleton element. This creates a wave effect that's more visually pleasing than all elements shimmering in sync.
Profile Card Skeleton

Complete skeleton for a profile card with cover image, avatar, name, bio, and stats.

profile-skeleton
Live
untitled.html
HTML
1<div class="profile-sk">
2 <div class="sk-cover">
3 </div>
4 <div class="sk-avatar-wrap">
5 <div class="sk-avatar">
6 </div>
7 </div>
8 <div class="profile-body">
9 <div class="sk-line w40 centered">
10 </div>
11 <div class="sk-line w60 centered sm">
12 </div>
13 <div class="sk-line w100">
14 </div>
15 <div class="sk-line w90">
16 </div>
17 <div class="sk-line w70">
18 </div>
19 <div class="sk-stats">
20 <div class="sk-stat">
21 <div class="sk-line w100">
22 </div>
23 <div class="sk-line w60 sm">
24 </div>
25 </div>
26 <div class="sk-stat">
27 <div class="sk-line w100">
28 </div>
29 <div class="sk-line w50 sm">
30 </div>
31 </div>
32 <div class="sk-stat">
33 <div class="sk-line w100">
34 </div>
35 <div class="sk-line w70 sm">
36 </div>
37 </div>
38 </div>
39 </div>
40</div>
preview
📝

note

Profile card skeletons need a negative margin on the avatar to overlap the cover image. Always account for this layout offset in the skeleton so it matches the final rendered card exactly.
Feed Skeleton

Skeleton for a social media feed post with user info, text content, image placeholder, and action buttons.

feed-skeleton
Live
untitled.html
HTML
1<div class="feed-sk">
2 <div class="post-sk">
3 <div class="post-header">
4 <div class="sk-circle sm">
5 </div>
6 <div class="hdr-lines">
7 <div class="sk-line w40">
8 </div>
9 <div class="sk-line w25 xs">
10 </div>
11 </div>
12 </div>
13 <div class="post-body">
14 <div class="sk-line w100">
15 </div>
16 <div class="sk-line w85">
17 </div>
18 <div class="sk-line w60">
19 </div>
20 </div>
21 <div class="sk-post-img">
22 </div>
23 <div class="post-actions">
24 <div class="sk-action">
25 </div>
26 <div class="sk-action">
27 </div>
28 <div class="sk-action">
29 </div>
30 </div>
31 </div>
32</div>
preview

best practice

Always include the same structural elements in your skeleton that appear in the real content — header, body, image, actions. Users subconsciously recognize the layout pattern, making the transition from skeleton to content feel seamless.
Reduced Motion

A static skeleton for users who prefer reduced motion, or as a fallback while shimmer keyframes load.

reduced-motion-skeleton
Live
untitled.html
HTML
1<div class="wrap">
2 <div class="sk-line w100">
3 </div>
4 <div class="sk-line w80">
5 </div>
6 <div class="sk-line w60">
7 </div>
8</div>
preview

warning

Respect prefers-reduced-motion. Replace shimmer animations with static placeholders for users who have disabled motion, or expose a user preference toggle in your app settings.
Accessibility

Skeletons are visual by nature, but screen-reader users and keyboard navigators still need context. Treat loaders as temporary state and avoid trapping focus or announcing every placeholder.

  • Wrap skeleton regions with aria-busy="true" on the live region or container while loading.
  • Use aria-live="polite" so finished content is announced once, not placeholder shapes.
  • Do not focus skeleton elements; keep focus on the trigger or move it to the loaded content.
  • Honor prefers-reduced-motion by disabling shimmer animations.
  • Ensure skeleton colors meet contrast ratios against the background, even while animated.
  • Provide a text fallback or label for any data that may fail to load.

Community

Get help on Slack, Discord or VIP

Stuck on a guide? Join the community and ask.