Natural Sticky Logo

Natural Sticky

Hide-on-scroll that flows naturally with your scroll speed - no jarring animations

Only 1.2KB β€’ Zero Animations β€’ Event-Driven β€’ Multiple Elements

🎈

Ultra Lightweight

Just 1.2KB minified for headers, 1.3KB for footers. 3.6x smaller than Headroom.js with zero dependencies and maximum performance.

🀹

Multiple Elements

Animate multiple headers, footers, and floating elements simultaneously without conflicts. Traditional sticky or floating modes for maximum flexibility.

🌊

Natural Movement

No jarring animations or sudden pop-ins. Elements flow naturally with your scroll speed, creating seamless movement that doesn't break focus.

πŸŽ›οΈ

Highly Customizable

Fine-tune behavior with precise parameters for snapping and activation, or build dynamic UIs with a powerful event system that reports state changes.

Live Demos

Try scrolling in the embedded demos below, or click to open them full-screen

🧠 How It Works

Open Full Demo β†’

🀹 Multiple Elements

Open Full Demo β†’

🚦 ScrollThreshold Comparison

Open Full Demo β†’

🧲 SnapEagerness Comparison

Open Full Demo β†’

πŸ“‘ Events System

Open Full Demo β†’

Additional Demos

🚦 ScrollThreshold Side-by-Side β†’ 🧲 SnapEagerness Side-by-Side β†’
⬆️ Basic Header Only β†’ ↕️ Header + Footer Together β†’ ⬇️ Basic Footer Only β†’

Code Examples (Minimal Styling)

Stripped-down demos focusing on implementation details

⬆️ Minimal Header ⬇️ Minimal Footer β¬†οΈπŸ›Έ Minimal Floating Header β¬‡οΈπŸ›Έ Minimal Floating Footer
β¬†οΈπŸ“‘ Minimal Header Events β¬‡οΈπŸ“‘ Minimal Footer Events β¬†οΈπŸ›ΈπŸ“‘ Minimal Floating Header Events β¬‡οΈπŸ›ΈπŸ“‘ Minimal Floating Footer Events β¬†οΈπŸ“‘πŸŽ¨ Minimal Header Style on Scroll

Quick Start

Option 1: CDN Usage

<!-- 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>

Option 2: Install and Import

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();

Configuration

reserveSpace (boolean, default: true)

Controls positioning behavior:

Live Demos: Floating Elements Demo β†’ | Minimal Floating Header β†’

snapEagerness (number, default: 1.0)

Balances natural movement vs gap prevention:

Live Demos: SnapEagerness Side-by-Side β†’ | SnapEagerness Comparison β†’

scrollThreshold (number, default: 0)

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 β†’

Events

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 β†’

Why Natural Sticky?

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:

View on GitHub β†’