react-on-sticky
A React implementation of
"An event for CSS position:sticky"
Note
This is a pre-release, put this on npm for now so I can use it already for a
personal project (unfortunately, i don't pay for npm private packages sob
someone donate)
Getting started
yarn add react-on-sticky
The package consists of three components:
- useStickyRoot (hook)
- useOnSticky (hook)
- StickyContainer
Usage
useOnStickyRoot
Use this hook within parent element/component of the targeted element which has
position: sticky
. Pass the ref provided by the hook into your parent element's
ref.
import { useOnStickyRoot } from 'react-on-sticky';
function MyScrollableParentElement() {
const [ stickyRootRef ] = useOnStickyRoot();
return (
<div
ref={stickyRootRef}
style={{
position: 'absolute';
overflowY: 'auto';
}}>
{ children }
</div>
);
}
StickyContainer
The sticky container must wrap the target element with position: sticky
. This
component will inject invisibble header/footer sentinels
which the
IntersectionObserver will keep track of. Please see the reference article above
in the introduction to learn more about the mechanics of this. Play around with
the height/offset of the sentinels to get the exact trigger you're looking for.
import { useOnStickyRoot, StickyContainer } from 'react-on-sticky';
function MyScrollableParentElement() {
const [ stickyRootRef ] = useOnStickyRoot();
return (
<div
ref={stickyRootRef}
style={{
position: 'absolute';
overflowY: 'auto';
}}>
<StickyContainer>
</StickyContainer>
</div>
);
}
useOnSticky
The hook that will receive the on sticky event. In the reference article, it
toggles a class. This does not do that, but it exposes a boolean isStuck
value
which you can then do anything under the sun with (including toggling
classNames).
Important note: Make sure that the element that has position:sticky
has a
className sticky
. Otherwise this won't work.
import { useOnStickyRoot, StickyContainer, useOnSticky } from 'react-on-sticky';
function MyScrollableParentElement() {
const [ stickyRootRef ] = useOnStickyRoot();
return (
<div
ref={stickyRootRef}
style={{
position: 'absolute';
overflowY: 'auto';
}}>
<StickyContainer>
</StickyContainer>
</div>
);
}
function MyStickyElement() {
const [ isStuck ] = useOnSticky();
useEffect(() => {
console.log(isStuck);
}, [isStuck]);
return (
<div
className="sticky"
style={{
position: 'sticky',
top: '10px',
}}>
I'm stuck!
</div>
);
}