React Sticky Node Component
react-stickynode is a performant and comprehensive React component for creating sticky elements on a webpage. Currently at version 5.0.2, it is actively maintained with regular dependency updates and support for new React versions, as evidenced by recent v5.x releases. This library differentiates itself by effectively handling not only standard sticky scenarios where the target is shorter than the viewport but also complex cases where the sticky content is taller. For tall sticky targets, it implements a natural scrolling behavior where the element scrolls until its bottom aligns with the viewport bottom (when scrolling down) or its top aligns with the viewport top (when scrolling up), maximizing content visibility. It also supports elements with percentage-based width units, making it suitable for responsive designs. Performance is prioritized through single `scrollTop` retrieval, throttled scroll listening, and rAF for status updates.
Common errors
-
TypeError: Sticky is not a constructor
cause Attempting to use `require()` for `react-stickynode` in an ES module environment or an incorrect default import method.fixChange your import statement to `import Sticky from 'react-stickynode';`. Ensure your bundler is configured to correctly handle ES module imports. -
Warning: Failed prop type: Invalid prop `children` supplied to `Sticky`
cause The `children` prop provided to the `Sticky` component does not conform to React's expected children types or the component's internal PropTypes.fixReview the children elements passed into `<Sticky>...</Sticky>`. Ensure they are valid React nodes (e.g., single element, array of elements, string). Check your console for more specific PropType validation messages to pinpoint the exact issue. -
Sticky element unexpectedly jumps, flickers, or does not stick at all.
cause Common causes include incorrect `top` or `bottomBoundary` values (especially when using string selectors that don't match existing DOM elements), conflicting CSS `position` or `z-index` rules, or issues with parent container overflow properties.fixFirst, confirm that any string selectors for `top` or `bottomBoundary` (e.g., `'#header'`) correctly identify elements in your DOM. Try using numerical values for `top` and `bottomBoundary` to rule out selector issues. Inspect element styles for conflicting `position: fixed`, `position: sticky`, or `z-index` properties. Ensure no parent elements have `overflow: hidden` which might clip sticky behavior.
Warnings
- breaking Starting from v4.0.0, `react-stickynode` publishes ES modules. Projects using CommonJS `require()` syntax might encounter issues or require specific bundler configurations to resolve the package correctly.
- gotcha Version 4.1.0 added initial React 18 support but was released with a known, unaddressed failing test case, indicating potential edge-case issues. While it unblocked users, full stability for React 18 was not fully guaranteed at that specific release point.
- breaking Version 5.0.0 updated the browserlist to target modern browsers. This change may lead to unexpected behavior or lack of support for very old or niche browser environments that were previously covered.
- gotcha Version 5.0.2 included a fix for the `children` PropType. While not a breaking change, developers previously relying on specific or potentially incorrect PropType behavior might observe stricter validation or changes in how children are handled.
Install
-
npm install react-stickynode -
yarn add react-stickynode -
pnpm add react-stickynode
Imports
- Sticky
const Sticky = require('react-stickynode');import Sticky from 'react-stickynode';
- StickyProps
import { StickyProps } from 'react-stickynode';import type { StickyProps } from 'react-stickynode'; - Default Export (Component)
import * as Sticky from 'react-stickynode';
import Sticky from 'react-stickynode';
Quickstart
import React from 'react';
import Sticky from 'react-stickynode';
const App = () => {
return (
<div>
<div style={{ height: '300px', background: '#eee', padding: '20px' }}>
Header Content (non-sticky)
</div>
<Sticky enabled={true} top={50} bottomBoundary={1200} innerZ={10}>
<div style={{ background: '#aaf', padding: '20px', border: '1px solid blue' }}>
<h2>This is a sticky component!</h2>
<p>It will stick to the top when you scroll down, 50px from the viewport top.</p>
<p>It will stop sticking when the bottom boundary (1200px from document top) is reached.</p>
<p>Scroll down to see it in action.</p>
</div>
</Sticky>
<div style={{ height: '1500px', background: '#fdd', padding: '20px' }}>
Main content area. Scroll here to test the sticky behavior.
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
{Array.from({ length: 20 }).map((_, i) => (
<p key={i}>More content line {i + 1}.</p>
))}
</div>
<div style={{ height: '200px', background: '#ccc', padding: '20px' }}>
Footer Content
</div>
</div>
);
};
export default App;