Newton's Cradle Loop
Five DOM pendulums aligned and swinging, exchanging momentum according to classical mechanics: lift one on one side, release it, and the one on the other side swings back at the same angle. The sequence restarts automatically every few seconds.
Updated
This effect is part of Effect.Labs — 840 vanilla effects, some free, some premium. Hover has 48 effects, including 5 free. Explore the category →
3 usage examples



How it works
Five div.nc384-wire (rods) each carry a div.nc384-bob (ball). Each rod pivots around its attachment point (transform-origin: center top) via an angle stored in a JavaScript array. The physics is a simple pendulum: on each frame, velocity += -G × sin(angle) × f with G = 0.004, then velocity *= 0.999^f (minimal damping) and angle += velocity × f. The step is normalised to 60 fps: f = dt / 16.67.
Momentum exchange is simulated by a toggle: when the leftmost pendulum returns to angle 0, its velocity is transferred to the next idle pendulum on the left, or vice versa on the right. This approximation is sufficient for the visual illusion. The launch sequence is predefined (levee counts down): every ~5 s, the leftmost pendulum is set to 0.5 rad and the sequence restarts. An IntersectionObserver pauses the loop off screen. Under reduced motion, pendulums are shown at a fixed vertical angle of 0.
Accessibility
- Reduced motion: under
prefers-reduced-motion: reduce, the loop does not start and the five pendulums are displayed vertical and fixed. The state is readable. - Keyboard and touch: the effect is not interactive. Pendulums swing on their own; nothing happens on click, touch or keypress.
- Decorative role: the zone has no ARIA role. If it illustrates content (a title, a concept), add the text next to the root and
aria-hidden="true"on.nc384-stage.
Browser compatibility
Pure DOM and CSS, no dependency. IntersectionObserver available since Chrome 51, Firefox 55, Safari 12.1. Physics via requestAnimationFrame normalised to elapsed time. Not verified on real Safari; expected full.
Without JavaScript, pendulums are shown vertical and fixed. Without IntersectionObserver, the loop also runs off screen.
The code
HTML structure to paste into your page (the CSS + JS come with your purchase):
<div class="fx-0384-root">
<div class="nc384-stage">
<div class="nc384-row"></div>
</div>
</div>
One-time payment, no subscription — the code is yours forever
Customize
Options passed to the API or data-* attributes:
| Option / property | Default | Effect |
|---|---|---|
| Pendulum count (JS — create N wires and bobs) | 5 | 3 gives a cleaner look; 7 a richer effect. Momentum exchange becomes less precise beyond 7 in this simplified implementation. |
Rod length (CSS — .nc384-wire { height: 150px }) |
150 px | 200 px slows the swing (longer period); 80 px speeds it up. |
Initial angle (JS — pendulums[0].angle = 0.5) |
0.5 rad (≈ 29°) | 0.8 rad (≈ 46°) gives wider, faster swings; 0.3 barely visible swaying. |
Damping (JS — velocity *= Math.pow(0.999, f)) |
0.999 — near lossless | 0.995 stops the pendulums within seconds; 0.9999 keeps them swinging for a very long time. |
Colour of rods and balls (CSS — .nc384-wire, .nc384-bob) |
indigo gradient, indigo balls | Use a solid hue for a minimalist look; use per-index colours for multicoloured balls. |
FAQ
pendulums array (a variable local to the closure). Edit their properties in the script lines: pendulums[0].angle = 0.5; pendulums[0].velocity = 0; restarts the sequence from the left. To trigger from outside the effect, first expose the reference or dispatch a custom event on the root.velocity *= 0.999^f) removes a tiny fraction of momentum on every frame. At 60 Hz, the swing lasts about 15 to 20 seconds before becoming imperceptible, then the script relaunches automatically.