Natural Sticky

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

Only 1.1KB โ€ข Zero Animations โ€ข Multiple Elements

๐ŸŽˆ

Ultra Lightweight

Just 1.1KB minified for headers, 1.2KB for footers. 4x 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.

๐ŸŽ›๏ธ

Fine-Tunable

Three precise parameters control natural feel, activation timing, and gap prevention. From pure natural movement to magnetic snapping, perfect for any use case.

Live Demos

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

โฌ†๏ธ Header (Default)

Open Full Demo โ†’

๐Ÿคน Multiple Elements

Open Full Demo โ†’

๐Ÿšฆ ScrollThreshold Comparison

Open Full Demo โ†’

๐Ÿงฒ SnapEagerness Comparison

Open Full Demo โ†’

Additional Demos

๐Ÿšฆ ScrollThreshold Side-by-Side โ†’ ๐Ÿงฒ SnapEagerness Side-by-Side โ†’
โ†•๏ธ 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

Quick Start

Install via NPM

npm install natural-sticky

Or use via CDN (just 1.0KB!)

<script src="https://cdn.jsdelivr.net/npm/natural-sticky/dist/natural-sticky.top.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>

With a bundler

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

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:

The secret is in switching between position: sticky and position: relative (or position: fixed and position: absolute for floating elements) at exactly the right moments, letting the browser's native scrolling handle all the movement naturally.

Choose your positioning style

The reserveSpace parameter (default: true) controls how elements behave:

Fine-tuning with snapEagerness

The snapEagerness parameter (default: 1.0) lets you balance between natural movement and gap prevention:

Controlling activation with scrollThreshold

The new scrollThreshold parameter (default: 0) controls when the natural scroll-in effect activates 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).

View on GitHub โ†’