Mercury Drops
Four chrome spheres from 50 to 80 px — 135° gray gradient, inner shadows, white highlight — jump 30 px while stretching, land squashed, bounce 15 px and settle, in a wave staggered by 0.2 s over a 2 s loop: hard, polished metal in pure CSS, resting still when the user reduces motion.
Updated
This effect is part of Effect.Labs — 840 vanilla effects, some free, some premium. Liquid has 31 effects, including 6 free. Explore the category →
3 usage examples



How it works
The container .mercury-container fills the root .fx-0397-root (300 px tall, navy gradient #1a1a2e → #0f0f1a) and lines up four .mercury-drop elements at the center, 20 px apart. Each sphere is a plain round div; the metal comes from three layers. A 135° linear gradient runs from very light gray #e8e8e8 to near black #2a2a2a through #a0a0a0 and #4a4a4a: the light comes from the top left. Two inner shadows carve the volume (black at 50% bottom right, white at 30% top left) and a 30 px drop shadow grounds the sphere. Finally the ::before pseudo-element, a white 80% radial gradient sized at 30%, placed 10% from the top and 15% from the left, makes the crisp highlight that says "polished".
The bounce is a single animation, mercuryBounce, 2 s long with ease-in-out. At 30% of the loop the sphere is 30 px higher, stretched (×0.9 wide, ×1.1 tall); at 50% it hits the ground squashed (×1.1 / ×0.9); at 70% it bounces 15 px, still slightly stretched; then it rests until the next loop. The four spheres have different sizes (60, 80, 60 and 50 px) and start with 0, 0.2, 0.4 and 0.6 s delays: the wave runs left to right. The squash happens around the sphere's center, not its contact point: on the ground, the bottom of the sphere lifts by a few pixels instead of flattening against it.
Only the transform property is animated: the browser hands the motion to the compositor and repaints neither the gradients nor the shadows. Measured in Chromium 151 over 3 s of animation: 0 ms of painting and rasterization, 0.42 ms of compositing per frame. Behavior is the same in Firefox 153 and WebKit 26 (7% of the frame's pixels change over 500 ms in all three). The container stretches over the root's full height (align-self: stretch): its gradient covers the whole frame.
Accessibility
- Reduced motion: under
prefers-reduced-motion: reduce, a block scoped to.fx-0397-rootremoves the animation: the four spheres rest side by side, with their highlights and shadows. Measured: 0% of pixels change over 500 ms in Chromium, Firefox and WebKit. - Decorative content: the spheres are empty
divelements with no text and no role, skipped by screen readers. If they stand for something (four diameters, four pieces of jewelry), write it under them, like the labels in the scenes above. - Contrast: the sphere's lit top (
#e8e8e8) measures 13.9:1 on the#1a1a2ebackground and carries the shape; the near-black bottom (#2a2a2a) blends into the background (1.2:1), on purpose for the sense of volume. On a light background it is the other way around: the dark bottom draws the outline. - Pace: a 2 s loop with no flashing; the highest jump is 30 px.
Browser compatibility
Pure CSS: linear and radial gradients, inner and outer box-shadow, transform animation, ::before pseudo-element. Zero JavaScript, no dependencies. Measured in Chromium 151, Firefox 153 and WebKit 26: same bounce, same wave, same stop under reduced motion; animation handled by the compositor (0 ms of painting measured in Chromium).
Without CSS animations, the four spheres rest in a row with their highlights: the metallic image holds without the motion.
The code
HTML structure to paste into your page (the CSS + JS come with your purchase):
<div class="fx-0397-root">
<div class="mercury-container">
<div class="mercury-drop"></div> … (4 spheres)
</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 |
|---|---|---|
Sizes (CSS — .mercury-drop and :nth-child(2), :nth-child(4)) |
60, 80, 60, 50 px | Each sphere can have its own size; the highlight and inner shadows follow (they use percentages or wide blurs). Below 30 px, reduce the inner shadows (20px → 10px) to keep the volume. |
Metal (CSS — linear-gradient(135deg, #e8e8e8 0, #a0a0a0 30%, #4a4a4a 70%, #2a2a2a 100%)) |
polished steel | Gold: #fff4c2, #e0b84a, #8a6418, #4a3308. Copper: #ffd2b8, #d0805a, #7a3a22, #3d1a0e. Keep the light → dark order for light from the top left. |
Jump height (CSS — -30px and -15px in mercuryBounce) |
30 px, 15 px rebound | Double both for livelier balls; keep the rebound at half the jump so the fall looks damped. Leave room above: the jump leaves the container if it is too short. |
Squash (CSS — scaleX(1.1) scaleY(.9) at 50%) |
±10% | ±20% for a soft ball, ±4% for very hard metal. Add transform-origin: 50% 100% to .mercury-drop so the squash starts from the ground rather than the center. |
Wave (CSS — animation-delay 0 / .2 / .4 / .6 s, 2s duration) |
0.2 s apart, 2 s loop | 0.5 s gaps give balls thrown one after another; 0 s, a jump in unison. |
Background and spacing (CSS — .mercury-container) |
#1a1a2e → #0f0f1a, 20 px gap, spheres centered | align-items: flex-end rests the spheres at the bottom of the container, on a floor; background: none puts them on your own background. |
FAQ
scale works from the element's center: when squashed by 10%, the sphere loses height at the top and the bottom, so its lowest point rises by a few pixels. Add transform-origin: 50% 100% to .mercury-drop: the squash then starts from the contact point and the sphere stays on the ground.transform moves: the browser keeps the already painted gradients and shadows and simply moves them. Measured in Chromium over 3 s: no painting, no rasterization, 0.42 ms of compositing per frame. Do not animate box-shadow or width instead: those are what would force repainting.