Reputation: 35
I use react with Material-UI for my website and I would like to add some transitions. I've used a button so far to make a component appear, but I want it to appear when I scroll to the component then the transition trigger. I am using <Grow/>
component from Material-UI, can you help me with that?
Upvotes: 2
Views: 4323
Reputation: 81390
You can listen to the scroll
event in the container element and detect whether the elements inside it is in the viewport like below:
function Scroller({ className, children, trackIds, onScrollToElement }) {
return (
<div
className={className}
onScroll={(e) => {
for (let i = 0; i <= trackIds.length - 1; i++) {
const id = trackIds[i];
const trackedEl = document.getElementById(id);
const scrollerEl = e.currentTarget;
if (
scrollerEl.scrollTop >
trackedEl.offsetTop + trackedEl.offsetHeight - scrollerEl.offsetHeight
) {
onScrollToElement(trackedEl);
}
}
}}
>
{children}
</div>
);
}
scrollerEl
is the scrollable container element. Make sure to set the overflow
CSS property of this element to auto
to show the scrollbar when there is not enough space.trackedEl
is the child element inside the scrollable container to keep track of, when the user scrolls to the trackedEl
, the callback onScrollToElement
is invoked.scrollerEl.scrollTop
: number of pixels scrolled vertically. This is the scroll 'progress'. Before you scroll, the value is 0
, as you are scrolling down the value is increase by the pixels you've scrolled.trackedEl.offsetTop + trackedEl.offsetHeight - scrollerEl.offsetHeight
: The number of pixels you have to scroll down to see the trackedEl
trackedEl.offsetTop
: The distance in pixel of the scrollerEl
top position to the trackedEl
top position.trackedEl.offsetHeight
: The height of trackedEl
including padding and border. This means you have to fully see the trackedEl
before onScrollToElement
firesscrollerEl.offsetHeight
: The height of scrollerEl
. Subtracting this because before you start scrolling, you've already seen the top part of the container.const classes = useStyles();
const [showButton, setShowButton] = useState(false);
return (
<Scroller
className={classes.container}
trackIds={["myButton"]}
onScrollToElement={(el) => {
if (el.id === "myButton" && !showButton) {
setShowButton(true);
}
}}
>
<div className={classes.topContent}>
<Typography variant="h4">Top content</Typography>
</div>
<div className={classes.buttonContent}>
<Grow in={showButton}>
<Button id="myButton" variant="contained" color="primary">
Primary
</Button>
</Grow>
</div>
</Scroller>
);
Props:
trackIds
: List of ids of the elements to keep track of in the Scroller
. If we track every elements inside Scroller
, it will affect the performance in complex UI.
onScrollToElement
: A callback that is executed when a tracked element is scrolled into view.
Upvotes: 1