Skip to content
animorio
IT
Back to the library

The weightless objects

Physics, 3D, HoverCSS onlyMediumCompressed weight: Demo 5.8 KBno librariesFreeDownload the zip

A giant title runs across the page like a ticker, and in front of its letters and behind them float cubes of glass, sugar, candy, rubber and chrome: they drift and turn, slow down to a quiet cruise, bounce off the edges and the bounce becomes spin. The pointer pushes them away.

The code

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 weightless objects</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/schibsted-grotesk@5.3.0/index.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <!-- the "not found" page of a made-up shop: a giant title runs across it like a ticker, and in front of it and
       behind it little cubes float with no weight, turning, drifting, bouncing off the edges; the pointer pushes them -->
  <div class="pagina">
    <header class="testa">
      <span class="testa__marchio">Paper Moon</span>
      <nav class="testa__voci" aria-label="Main">
        <a href="#">Shop</a>
        <a href="#">Journal</a>
        <a href="#">Contact</a>
      </nav>
    </header>
    <main class="cielo" data-cielo>
      <h1 class="sr">Page not found</h1>
      <div class="nastro" data-nastro aria-hidden="true">
        <ul class="nastro__fila" data-fila>
          <li class="nastro__voce" data-voce>Nothing here yet<svg class="nastro__segno" viewBox="0 0 40 40"><path d="M20 2 25 15 38 20 25 25 20 38 15 25 2 20 15 15Z"/></svg></li>
        </ul>
      </div>
      <div class="oggetto" data-oggetto data-taglia="large" data-materiale="glass" data-livello="davanti"></div>
      <div class="oggetto" data-oggetto data-taglia="medium" data-materiale="dice" data-livello="dietro"></div>
      <div class="oggetto" data-oggetto data-taglia="small" data-materiale="candy" data-livello="davanti"></div>
      <div class="oggetto" data-oggetto data-taglia="medium" data-materiale="sugar" data-livello="davanti"></div>
      <div class="oggetto" data-oggetto data-taglia="small" data-materiale="rubber" data-livello="dietro"></div>
      <div class="oggetto" data-oggetto data-taglia="large" data-materiale="chrome" data-livello="dietro"></div>
      <div class="oggetto" data-oggetto data-taglia="small" data-materiale="glass" data-livello="davanti"></div>
    </main>
    <footer class="piede">
      <a href="#">Back to the shop</a>
      <span>Error 404</span>
    </footer>
  </div>

  <script src="script.js"></script>
</body>
</html>

Playground

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

Or ask Claude Code for it

With the Animorio connector, Claude Code takes it from here, guide included, and fits it into your project. Paste this request:

Take “The weightless objects” from Animorio and fit it into my site

What it does

The «not found» page of a made-up shop, Paper Moon, on a bright pink: at the top the name and three links, at the bottom «Back to the shop» and «Error 404». Across the middle the giant words «Nothing here yet» run from right to left, endlessly, with a four-pointed star between one copy and the next. Seven cubes in three sizes pop in one after the other: two of bluish glass, a die, a sugar cube, a striped candy, one of green rubber and one of chrome. Each turns round in 3D without stopping and meanwhile drifts across the page in a random direction, also turning in the plane; it starts a little faster and slows down to a quiet speed it then keeps. When it touches an edge it bounces, and the knock makes it turn harder or the other way. Some pass in front of the letters, some behind. With the pointer near, a cube is pushed away and starts to spin.

How it works

Positions in fractions of the page

Each cube has a centre between 0 and 1 across and down, a speed in the same units per millisecond, an angle and a spin in degrees a millisecond. So the same numbers work at any size, and widening the window keeps the cubes where they are. The script only moves and turns each cube’s box, with a translate3d and a rotate.

The cruise

Each cube sets off in a random direction at a speed between 0.00006 and 0.00014, and every sixtieth of a second keeps 99.6% of the speed above the cruise of 0.0001: it slows down to there and then never stops. The spin starts at up to 0.02 degrees a millisecond and fades the same way.

The edges and the bounce

The edge that counts is that of the cube’s box turned by its angle: the half-size is half the side times the sum of |cos| and |sin|. Touching a wall the speed going into the wall is reversed, and the speed along the wall, times 150, is added to the spin; the spin never goes past 0.15 degrees a millisecond.

The push of the pointer

If the pointer is closer than 0.12 to a cube’s centre, the cube gets a push the other way, as strong as (1 − distance / 0.12) × 0.000001 per millisecond, and a spin in the direction of the push. Distances are in fractions of the page, so the pushing zone is a little wider than it is tall, as on the site.

The ticker and the 3D cubes

The title is a row of copies of the same words: as many as it takes to cover the page plus one, moved 0.15 pixels a millisecond and taken back by the width of one copy; those outside the page are hidden. Each cube is six faces in CSS 3D turning with an animation around a slanted axis, with a fake light: each face is lighter or darker by a fixed amount.

Values to change

NameFileDefaultWhat it changes
SPEEDscript.js[0.00006, 0.00014]The starting speed, at random between the two, in pages a millisecond.
CRUISEscript.js0.0001The speed every cube slows down to and then keeps.
DRAGscript.js0.996How much of the extra speed and spin is kept every sixtieth of a second.
SPINscript.js0.02The starting spin, at most, in degrees a millisecond.
SPIN_MAXscript.js0.15The fastest a cube may spin.
PUSHscript.js[0.12, 0.000001]The pointer: how near it pushes, in pages, and how hard.
KICKscript.js150How much a bounce or a push turns into spin.
TICKERscript.js0.15How fast the title runs, in pixels a millisecond.

Try them in the Playground

When to use it

For an error page, the header of an archive or the page of a studio or a shop that wants a little play without getting in the way: the objects move slowly, never cover anything for long and can be pushed.

On phones

The cubes are smaller and the title shorter; a finger sliding over the page pushes the nearby cubes as the pointer does.

With reduced motion

The title stays still, the cubes appear with a fade in their place, turned by a fixed angle, and do not move.

Pitfalls

  • On the site the drag is 0.996 a frame, so on a 120 Hz screen the cubes slow down twice as fast: here it is 0.996 every sixtieth of a second, raised to the time passed.
  • The edge of a turned cube is not its side: without the turned box, a cube lying askew goes half off the page before it bounces.
  • The 3D cube turns with a CSS animation and its box with the script: were they the same element, the script’s transform would wipe out the 3D turn.
  • The copies of the title are counted after the font has loaded: with the fallback font the words are shorter and a gap would be left at the end of the ticker.
  • The glass faces are half see-through and show through one another: that is why they keep backface-visibility visible, which changes nothing for the other materials.

Libraries

Schibsted Grotesk (font variabile) 5.3.0.

Compressed with gzip, the three demo files weigh 5.8 KB, and no libraries are needed.

Testing

Tested on 6 October 2026

  • Desktop: Done
  • Phone: Done
  • Reduced motion: Done
  • Safari on iPhone: To do

License

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.

All animations