Hide-on-scroll that flows naturally with your scroll speed - no jarring animations
Only 1.2KB β’ Zero Animations β’ Event-Driven β’ Multiple Elements
Just 1.2KB minified for headers, 1.3KB for footers. 3.6x smaller than Headroom.js with zero dependencies and maximum performance.
Animate multiple headers, footers, and floating elements simultaneously without conflicts. Traditional sticky or floating modes for maximum flexibility.
No jarring animations or sudden pop-ins. Elements flow naturally with your scroll speed, creating seamless movement that doesn't break focus.
Fine-tune behavior with precise parameters for snapping and activation, or build dynamic UIs with a powerful event system that reports state changes.
Try scrolling in the embedded demos below, or click to open them full-screen
Stripped-down demos focusing on implementation details
β¬οΈ Minimal Header β¬οΈ Minimal Footer β¬οΈπΈ Minimal Floating Header β¬οΈπΈ Minimal Floating Footer
<!-- For headers (1.2KB minified) -->
<script src="https://cdn.jsdelivr.net/npm/natural-sticky/dist/natural-sticky.top.min.js"></script>
<!-- For footers (1.3KB minified) -->
<script src="https://cdn.jsdelivr.net/npm/natural-sticky/dist/natural-sticky.bottom.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', () => {
const header = document.querySelector('.my-header');
// Default behavior (traditional sticky)
window.naturalStickyTop(header);
// Floating elements mode
window.naturalStickyTop(header, { reserveSpace: false });
// Fine-tune with scrollThreshold and snapEagerness
window.naturalStickyTop(header, {
snapEagerness: 2.0,
scrollThreshold: 10, // Only activate on medium-speed scrolling
reserveSpace: true // Traditional sticky (default)
});
});
</script>
npm install natural-sticky
import { naturalStickyTop, naturalStickyBottom } from 'natural-sticky';
// For headers (traditional sticky by default)
const headerInstance = naturalStickyTop(document.querySelector('.header'));
// For footers with floating elements mode
const footerInstance = naturalStickyBottom(document.querySelector('.footer'), {
reserveSpace: false
});
// Fine-tune all parameters
const customHeader = naturalStickyTop(document.querySelector('.header'), {
snapEagerness: 2.0, // More eager snapping to prevent visual gaps
scrollThreshold: 15, // Only activate on moderate to fast scrolling
reserveSpace: true // Traditional sticky (default)
});
// Clean up when needed
headerInstance.destroy();
footerInstance.destroy();
Controls positioning behavior:
Live Demos: Floating Elements Demo β | Minimal Floating Header β
Balances natural movement vs gap prevention:
Live Demos: SnapEagerness Side-by-Side β | SnapEagerness Comparison β
Controls activation based on scroll speed:
Perfect for creating more intentional user interactions. Headers might use lower thresholds (always accessible), while footers might use higher thresholds (only appear during deliberate navigation).
Live Demos: ScrollThreshold Side-by-Side β | ScrollThreshold Comparison β
Natural Sticky dispatches events when elements change state, enabling dynamic interfaces that respond to scroll behavior:
const header = document.querySelector('.header');
naturalStickyTop(header);
// Listen for state changes
header.addEventListener('natural-sticky', (event) => {
const currentState = event.detail.state; // 'home', 'sticky', or 'relative'
// Apply different styles based on state
header.classList.remove('state-home', 'state-sticky', 'state-relative');
header.classList.add(`state-${currentState}`);
console.log(`Header is now: ${currentState}`);
});
Live Demo: Event System Demo β
Traditional sticky headers use CSS transitions or JavaScript animations that can feel jarring and disconnected from the user's scroll behavior. Natural Sticky takes a different approach: