Skip to content

Latest commit

 

History

History
205 lines (167 loc) · 7.89 KB

File metadata and controls

205 lines (167 loc) · 7.89 KB

React Sticky Kit

NPM Version NPM Downloads GitHub Stars Build Status License TypeScript SSR/SSG Compatible

A lightweight, flexible React sticky container and item component library. Easily create sticky headers, sections, and advanced sticky layouts with support for multiple modes and edge cases.

Features

  • 📦 Simple API: <StickyContainer> and <StickyItem>
  • 🧩 Supports replace, stack, and none sticky modes
  • 🏷️ Customizable offset, z-index (baseZIndex), and sticky logic
  • 🖥️ Flexible reference containers (window, DOM elements, refs)
  • 🔄 Supports SSR/SSG (Next.js, Gatsby, Astro, etc.)
  • 🧪 Handles edge cases: empty sections, dynamic heights, zero-height headers, long headers, etc.
  • ⚡️ Written in TypeScript, fully typed
  • 🧪 Includes demo pages for real-world scenarios

Installation

npm install react-sticky-kit
# or
yarn add react-sticky-kit
# or
pnpm add react-sticky-kit

Demo

Usage

import { StickyContainer, StickyItem } from 'react-sticky-kit';
// !! Import styles for sticky components
import 'react-sticky-kit/dist/style.css';
// or `import 'react-sticky-kit/style';` for more clean style path(require modern bundler tools)

export default function Example() {
  return (
    <StickyContainer offsetTop={48} defaultMode="stack" baseZIndex={300}>
      <StickyItem>
        <div>Sticky Header</div>
      </StickyItem>
      <div>Content...</div>
      <StickyItem mode="replace">
        <div>Another Sticky Header (replace mode)</div>
      </StickyItem>
      <div>More Content...</div>
    </StickyContainer>
  );
}

Props

<StickyContainer />

Prop Type Default Description
offsetTop number 0 Offset from the top of the viewport
defaultMode 'replace' | 'stack' | 'none' 'replace' Default sticky mode for all items
baseZIndex number 200 Base z-index for sticky items. Should be greater than the number of sticky items.
In replace mode, z-index = baseZIndex - index; in stack mode, z-index = baseZIndex + index.
onStickyItemsHeightChange (height: number) => void Callback when total sticky height changes
constraint 'none' Define the constraint for sticky behavior. 'none' = no constraints (CSS-like behavior)

<StickyItem />

Prop Type Default Description
mode 'replace' | 'stack' | 'none' Sticky mode for this item (overrides StickyContainer)

Sticky Modes

  • replace: Only one sticky item is visible at a time, replacing the previous.
  • stack: Sticky items stack on top of each other.
  • none: Sticky is disabled for this item.

Constraint Behavior

The constraint prop allows you to control when sticky items should stop being sticky:

import React from 'react';
import { StickyContainer, StickyItem } from 'react-sticky-kit';

function Example() {
  return (
    <div>
      {/* 1. Default: Container-based constraint */}
      <StickyContainer>
        <StickyItem><div>Sticky stops when container leaves viewport</div></StickyItem>
        <div>Content...</div>
      </StickyContainer>
      
      {/* 2. No constraints (like CSS position:sticky) */}
      <StickyContainer constraint="none">
        <StickyItem><div>Always sticky like CSS position:sticky</div></StickyItem>
        <div>Content...</div>
      </StickyContainer>
    </div>
  );
}
        <div>Content...</div>
      </StickyContainer>
    </div>
  );
}

Special behavior of constraint="none"

When you set constraint="none", the sticky items will always stick when they reach the top of the viewport, regardless of their parent container's visibility. This exactly matches the behavior of native CSS position: sticky.

In contrast, the default behavior (without specifying a constraint) only makes items sticky when their parent container is visible in the viewport.

Demo

Run the demo locally:

pnpm install
pnpm dev

Open http://localhost:5173 and switch between demo pages to explore all features and edge cases:

SSR/SSG Support

React Sticky Kit supports Server-Side Rendering (SSR) and Static Site Generation (SSG), working seamlessly with frameworks like Next.js, Gatsby, Astro, and more.

Next.js Example

// pages/index.tsx
import { StickyContainer, StickyItem } from 'react-sticky-kit'
import 'react-sticky-kit/dist/style.css'

export default function Home() {
  return (
    <StickyContainer>
      <StickyItem>
        <header>Sticky Header</header>
      </StickyItem>
      <main>Content...</main>
    </StickyContainer>
  )
}

Astro Example

---
// src/pages/index.astro
import { StickyContainer, StickyItem } from 'react-sticky-kit'
import 'react-sticky-kit/dist/style.css'
---

<html>
  <head>...</head>
  <body>
    <StickyContainer client:load>
      <StickyItem>
        <header>Sticky Header</header>
      </StickyItem>
      <div>Content...</div>
    </StickyContainer>
  </body>
</html>

Publish steps

pnpm pub

License

MIT