Pure Natural Movement (snapEagerness: 0.0)
Configuration: { snapEagerness: 0.0 }
This header uses the most natural feel but may occasionally show small visual gaps when scrolling up quickly.
💡 Testing tip: Try scrolling at different speeds. Notice how the movement feels completely natural and connected to your scroll speed.
🔍 What Makes This "Natural"?
With snapEagerness set to 0.0, the header only becomes sticky when it naturally reaches the top edge, with no prediction or early switching. This creates the most organic feel.
Key characteristics:
- ✅ Perfect natural feel - header truly becomes part of content flow
- ✅ Movement matches your exact scroll input with zero anticipation
- ✅ Most intuitive and least distracting behavior
- ⚠️ May show brief gaps during very fast upward scrolling
📋 The Source Code Behind This Behavior
Here's the actual TypeScript implementation that powers this natural movement:
/**
* Natural sticky behavior with configurable snap eagerness
*/
export function naturalStickyTop(element: HTMLElement, options: { snapEagerness?: number } = {}) {
const { snapEagerness = 1.0 } = options;
let lastScrollY = window.scrollY;
let mode = 'relative';
const handleScroll = () => {
const currentScrollY = window.scrollY;
const scrollingDown = currentScrollY > lastScrollY;
const scrollingUp = currentScrollY < lastScrollY;
const elementHeight = element.offsetHeight;
const elementRect = element.getBoundingClientRect();
const isElementVisible = elementRect.bottom > 0 && elementRect.top < window.innerHeight;
// Calculate scroll velocity for prediction
const scrollVelocity = currentScrollY - lastScrollY;
const predictedTop = elementRect.top - snapEagerness * scrollVelocity;
// If we are sticky and scroll down, release the element
if (mode === 'sticky' && scrollingDown) {
mode = 'relative';
element.style.position = 'relative';
element.style.top = `${currentScrollY}px`;
}
// If scrolling up and element not visible, prepare for reveal
else if (mode === 'relative' && scrollingUp && !isElementVisible) {
element.style.position = 'relative';
element.style.top = `${currentScrollY - elementHeight}px`;
}
// With snapEagerness 0.0, only snap when naturally reaching the top
else if (mode === 'relative' && predictedTop >= 0) {
mode = 'sticky';
element.style.position = 'sticky';
element.style.top = '0';
}
lastScrollY = currentScrollY > 0 ? currentScrollY : 0;
};
handleScroll();
window.addEventListener('scroll', handleScroll, { passive: true });
return { destroy: () => window.removeEventListener('scroll', handleScroll) };
}
🎯 When to Choose snapEagerness: 0.0
This setting is perfect when:
- Natural movement is your top priority - Users will feel the most intuitive connection
- Content-focused sites - Reading experiences where distraction should be minimized
- Desktop-first designs - Mouse wheel scrolling is typically more controlled
- Performance-critical applications - Minimal prediction logic reduces computation
⚠️ Potential Trade-offs
Be aware that with pure natural movement:
- Very fast scrolling may occasionally show brief visual gaps
- Mobile users with momentum scrolling might notice more artifacts
- Complex header layouts may appear less polished during edge cases
Continue scrolling to test different scroll speeds and patterns. Pay attention to how the header responds to your exact scroll input without any anticipation.
Try these specific tests:
- Slow, steady scrolling: Should feel perfectly smooth
- Quick direction changes: Notice the immediate response
- Fast upward scrolling: This is where you might see occasional gaps
- Momentum scrolling: (Mobile/trackpad) Watch behavior during deceleration
📊 Comparing with Other Values
This 0.0 value represents one end of the spectrum:
- snapEagerness: 0.0 ← You are here (Pure natural)
- snapEagerness: 1.0 - Balanced default (1 step prediction)
- snapEagerness: 2.0 - Eager gap prevention (2 step prediction)
- snapEagerness: 3.0 - Magnetic effect (3 step prediction)
The higher the value, the more the system "anticipates" your scrolling to prevent gaps, but at the cost of natural feel.
This is where the pure natural movement really shines - there's no artificial prediction interfering with the organic flow of your scrolling motion.
Keep scrolling to continue testing!
The more you scroll, the better you'll feel the pure natural
movement.