
The ticker in the button
Hover, SVG, Text
NewFree
A sundial seen from above, a fan of hairline ticks and a gnomon: the pointer is the sun, the shadow turns and stretches on two springs, the digits of the time click over one by one and underneath the time is written in words, half past four, letter by letter. Minimal style.
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 sundial that tells the time</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/fraunces@5.3.0/full.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/instrument-sans@5.3.0/wdth.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<!-- a sundial seen from above: a fan of hairline ticks and a gnomon. The pointer is the sun: its shadow swings
and stretches on a spring, the time is written underneath in words and its digits click over -->
<main class="stage" data-stage>
<header class="top">
<span class="top__name">Meridian</span>
<span class="top__note">A sundial, seen from above</span>
</header>
<div class="dial" role="slider" tabindex="0" aria-label="Time of day" aria-valuemin="5" aria-valuemax="19" data-dial>
<svg class="dial__svg" viewBox="-500 -490 1000 720" aria-hidden="true">
<defs>
<linearGradient id="shade" gradientUnits="userSpaceOnUse" x1="0" y1="0" x2="0" y2="-300" data-shade>
<stop offset="0" stop-opacity="0.82"></stop>
<stop offset="0.7" stop-opacity="0.42"></stop>
<stop offset="1" stop-opacity="0.08"></stop>
</linearGradient>
</defs>
<path class="rim" data-rim></path>
<path class="path" data-sunpath></path>
<path class="ticks" data-ticks></path>
<path class="ticks ticks--hours" data-hours></path>
<path class="ticks ticks--now" data-now></path>
<g data-shadow-turn><path class="shadow" fill="url(#shade)" data-shadow></path></g>
<path class="gnomon" data-gnomon></path>
<path class="sun" data-sun></path>
</svg>
<div class="labels" aria-hidden="true" data-labels></div>
</div>
<div class="read" aria-hidden="true">
<div class="read__row">
<span class="digits" data-digits>
<span class="slot" data-slot></span><span class="slot" data-slot></span><span class="digits__colon">:</span><span class="slot" data-slot></span><span class="slot" data-slot></span>
</span>
<span class="read__date" data-date>June 21</span>
</div>
<div class="words" data-words></div>
</div>
<p class="hint">Move the sun across the page</p>
</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.
23 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 sundial that tells the time” from Animorio and fit it into my siteOn a horizontal sundial the style's shadow at time t makes an angle with the noon line given by tan(angle) = sin(latitude) × tan(H), where H is the sun's hour angle, 15 degrees for each hour from noon. With atan2(sin(lat)·sin H, cos H) the angle stays continuous past six o'clock, so the ticks run from 5 to 19 and close up round noon by themselves. The SVG has a viewBox of 1000 by 720 with the gnomon at the origin; each tick is a segment to the rim (radius 420), in two paths: the hours darker, the rest lighter.
The pointer's horizontal position becomes the hour (right is dawn, left is sunset), the vertical one the season, that is the sun's declination between +23.44 and −23.44 degrees. From hour and season comes the sun's height, sin(h) = sin(lat)·sin(dec) + cos(lat)·cos(dec)·cos(H), and the shadow of a gnomon NODUS tall is NODUS / tan(h) long, with the sun never below 5 degrees so the shadow stays on the dial. The day next to the digits comes from the same declination, read on the way from December to June.
The time the shadow shows goes towards the one the sun asks for on TIME_SPRING, integrated by hand on GSAP's ticker with the step capped at 1/30 of a second; the length goes towards the one of that moment on LENGTH_SPRING, softer, so when the shadow turns fast it stretches and shrinks a little late and with a hair of bounce. The shadow is a wedge drawn pointing up inside a rotated group: the userSpaceOnUse gradient turns with it and always fades towards the tip. The ticks nearby have a spring each, which pulls them in towards the middle in proportion to the speed (LEAN).
Each digit sits in a little window with hidden overflow: the new digit comes in from below (from above if time goes back) on back.out and the old one leaves the other way, fading. If a digit changes again within 0.24 seconds it simply switches without rolling, so they do not pile up when time runs fast. The words are rounded to five minutes; they are rewritten when the phrase stays the same for 0.22 seconds, or at most once every 0.85 seconds while the shadow runs. Each letter is a span with font-weight: calc(var(--wt) + var(--lw)): the container gives the weight of the speed (WEIGHT), the landing letter takes --lw from −300 to 0.
A GSAP timeline draws the rim and the sun's path opening them from the middle, grows each tick with a back.out when the drawing reaches it, raises the gnomon with elastic.out, then takes the sun from 5 to START: the springs do the rest. The mouse drives the sun anywhere on the page, a finger while it drags; the dial is a role=slider with the arrow keys. After 2.4 seconds with nobody there, a gsap.delayedCall moves the sun on half an hour every 1.5 seconds.
| Name | File | Default | What it changes |
|---|---|---|---|
TIME_SPRING | script.js | [150, 17] | The spring the shadow turns on: how stiff, and how much it is held back (less hold, more bounce). |
LENGTH_SPRING | script.js | [210, 11] | The spring the shadow stretches and shrinks on: how stiff, and how much it is held back. |
NODUS | script.js | 140 | How tall the gnomon is (the dial is 1000 wide): taller, longer shadows. |
LEAN | script.js | 18 | How far the ticks next to the shadow reach in towards the middle while it runs. |
WEIGHT | script.js | [540, 220] | The weight of the words at rest and while the shadow runs (100 to 900). |
WIDTH | script.js | [100, 76] | The width of the digits at rest and while they count fast (75 to 100). |
START | script.js | 16.5 | The hour the opening lands on, from 5 to 19 (16.5 is half past four). |
WANDER | script.js | true | The sun walks on by itself, half an hour at a time, when nobody moves the pointer. |
To tell a time in a warm, readable way: a restaurant's or a bar's opening hours (when lunch is served, when it closes), a hotel's or a holiday home's check-in time, the time of a concert or an event, sunset from a terrace. It works where the time is the message and there is room for a single scene; for one time among lots of data plain text is enough.
The same animations with the sizes adapted: the dial is as wide as the screen, the hour numbers and the digits a little smaller, the words scale with the width. The sun follows the finger while it drags anywhere on the page (the page does not scroll there, it is a single scene) and stops when it lifts; then it walks on by itself.
No springs, no ticks reaching in, no rolling digits and no sun walking by itself: the shadow goes straight to the hour and its length, the digits change and the words swap with a short fade. When the page opens everything fades in already in place, at half past four.
GSAP 3.15.0, Fraunces (font variabile) 5.3.0, Instrument Sans (font variabile) 5.3.0.
Compressed with gzip, the three demo files weigh 9.6 KB; the libraries: GSAP 28 KB.
Tested on 15 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.