Magnetic Header
Written: 18 Feb, 2026
I wanted my site’s header to feel physical. Not just sticky, but, magnetic. On scrolling down, the header pulls itself to the top edge of the viewport. Scrolling back up releases it as it drifts to its resting position. Like a watch snapping onto a magnetic charger!
The starting point
A sticky nav bar, floating 16px from the top, with a box-shadow and 4px rounding. I reached for Motion for the transition — spring physics felt right for something magnetic. Springs accelerate as they approach, then settle on contact.
Iteration 1: Stiff spring
stiffness: 400, damping: 25. The top offset animates from 16px to 0, border-radius flattens at the top when docked.
The spring resolved so fast you couldn’t perceive any motion. It just moved. There was no sense of pull.
Iteration 2: Softer spring, plus a squeeze
Loosened to stiffness: 300, damping: 18 for more visible overshoot. Added a horizontal squeeze: on dock, the header compresses to scaleX(0.985) and springs back. On undock, a slight exhale to scaleX(1.005). Two separate animate() calls — one for position, one for scale.
This, however, was jittery. Two competing springs on the same element created a visual conflict—horizontal wobble layered on top of vertical movement.
Iteration 3: Squeeze removed
Backed out the scaleX animations. Just the softer position spring.
Cleaner, but the dock was missing something. The header moved to the right place without feeling like it arrived.
Iteration 4: Expand instead of squeeze
What if the header expanded on dock instead of compressing? scaleX: 1.012 when docked, back to 1 on undock. This time, the scale was part of the same animate call as the position: one spring driving both properties.
The expand gave the dock weight. But the spring was still loose: a visible bounce on landing that read as elastic, not magnetic. The damping needed to go up.
Iteration 5: The final version
stiffness: 380, damping: 28. Fast pull, immediate settle. The expand stays at scaleX: 1.012. The undock uses a different spring: stiffness: 200, damping: 30. This was softer, slower. Magnets snap on harder than they come off.
No bounce. The header pulls up, widens slightly, lands. The asymmetry between dock and undock seems to have worked.
What I took away
Damping controls character more than stiffness does. Stiffness is speed. Damping is whether the spring overshoots, wobbles, or stops dead. For a magnetic interaction, both need to be high: fast and decisive.
The scaleX expand only worked when it was part of the same animate call as the position. As a separate spring, it jittered. Unified, it became part of one gesture.