
The menu that opens from its button
Menus, Transitions, Text
Free
A profile card that opens as a skeleton of grey bones with a single glint crossing them all; once loaded, each bone turns into its piece from the top down: the cover is uncovered as its hills rise, the avatar opens like an iris, the words are wiped in and the numbers count up.
A folder that runs on its own: index.html, style.css, script.js and the libraries from a CDN. The React and Vue tabs hold the same demo as a ready component, which switches its animations off when it leaves the page.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>The loading skeleton</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/hanken-grotesk@5.3.0/index.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="stage">
<!-- the card: while it loads every piece is a grey bone, and one glint runs across all of them together. Loaded,
each bone turns into its piece from the top down: the cover uncovers its hills, the avatar opens, the words
are wiped in, the numbers count up and the button fills -->
<div class="profile" data-profile>
<article class="card is-loading" aria-busy="true" aria-label="Profile" data-card>
<div class="card__cover bone" data-bone="cover">
<svg class="card__hills" viewBox="0 0 360 132" preserveAspectRatio="none" aria-hidden="true">
<rect width="360" height="132" fill="#ffe3cf"/>
<path data-hill d="M0 70 C60 40 110 52 170 66 C230 80 290 44 360 58 V132 H0z" fill="#ffc6a6"/>
<path data-hill d="M0 92 C70 70 130 84 190 92 C250 100 300 76 360 86 V132 H0z" fill="#f59b7a"/>
<path data-hill d="M0 112 C80 96 150 106 220 112 C280 117 320 102 360 108 V132 H0z" fill="#d9715a"/>
</svg>
</div>
<div class="card__body">
<div class="card__row">
<span class="card__avatar bone" data-bone="avatar"><span class="card__face" aria-hidden="true">EM</span></span>
<button class="card__follow bone" type="button" data-bone="button"><span>Follow</span></button>
</div>
<h2 class="card__name"><span class="bone" data-bone>Elena Marchetti</span></h2>
<p class="card__role"><span class="bone" data-bone>Illustrator in Bologna</span></p>
<p class="card__bio">
<span class="bone" data-bone>Draws maps of places that do not</span>
<span class="bone" data-bone>exist yet. Ink, watercolour and far</span>
<span class="bone" data-bone>too much tea.</span>
</p>
<dl class="card__stats">
<div><dt class="bone" data-bone>Posts</dt><dd class="bone" data-bone data-count="128">128</dd></div>
<div><dt class="bone" data-bone>Followers</dt><dd class="bone" data-bone data-count="14200" data-short>14.2k</dd></div>
<div><dt class="bone" data-bone>Following</dt><dd class="bone" data-bone data-count="311">311</dd></div>
</dl>
</div>
</article>
<button class="reload" type="button" data-reload data-autoclic>
<svg viewBox="0 0 24 24" aria-hidden="true" data-reload-icon><path d="M19.5 12a7.5 7.5 0 1 1-2.2-5.3M19.5 4.5v4.2h-4.2"/></svg>
<span>Load again</span>
</button>
<p class="sr" role="status" aria-live="polite" data-said></p>
</div>
</main>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/gsap.min.js"></script>
<script src="script.js"></script>
</body>
</html>Change values, colours and text with the controls and watch the animation respond live. Or write in the code yourself. Then download the folder with your changes.
24 values to change
With the Animorio connector, Claude Code takes it from here, guide included, and fits it into your project. Paste this request:
Take “The loading skeleton” from Animorio and fit it into my siteThe script puts a veil (an i element) inside every piece marked with data-bone. The words sit in inline-block elements, so the veil takes their width, and it is a little thinner than the line; under the veil the words stay see-through until their turn.
All the veils have the same gradient, twice as wide as the card, shifted by how far right the veil is (--x) and by where the glint is (--b): background-position is --b − --x − --cw. A tween takes --b from one side of the card to the other in SWEEP seconds, over and over.
Once the card has loaded, the bones line up from the top and from the left, STAGGER seconds apart: each veil shrinks with scaleX towards the right in WIPE seconds, uncovering its piece from the left. The cover’s hills rise one after another, the words drop 5 pixels into place, the avatar’s veil fades and the face opens with a circle clip-path.
Each number keeps the width of its final figure (taken at the start as min-width), so the veil and the row do not move while it counts; the count goes from zero to the figure with power3.out, and 14200 is written 14.2k.
Load again puts the veils back from the left, one every 0.025 seconds, starts the glint again and after LOAD seconds uncovers the card once more. The card has aria-busy while it loads, and a line for screen readers says when it is ready.
| Name | File | Default | What it changes |
|---|---|---|---|
LOAD | script.js | 1.6 | The seconds the bones show before the card has loaded. |
SWEEP | script.js | 1.15 | The seconds the glint takes to cross the card. |
WIPE | script.js | 0.55 | The seconds a bone takes to turn into its piece. |
STAGGER | script.js | 0.06 | The seconds between a piece and the next, from the top down. |
For anything that comes from a server and keeps you waiting a moment: profiles, product cards, articles, lists of results, dashboards.
The card takes the width of the screen minus a margin; bones and glint adjust by themselves, because the script measures the veils again when the card changes size. Two quick taps on Load again do not zoom the page.
No glint, no rising hills and no counting: the bones stay still and, once the card has loaded, they all fade together leaving the pieces in place.
GSAP 3.15.0, Hanken Grotesk (font variabile) 5.3.0.
Compressed with gzip, the three demo files weigh 5.2 KB; the libraries: GSAP 28 KB.
Tested on 3 October 2026
Use it in your own projects and in your clients’ projects. Do not resell it or redistribute it as is. GSAP stays under its own Standard license. Full license.
With your account’s email and password.
or with your email
You’re signed in as .
With your account, you can download the zip of every animation and every pack, for free.