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?
Asked
Active
Viewed 2,945 times
2

NearHuscarl
- 66,950
- 18
- 261
- 230

Vali Talpas
- 35
- 1
- 6
1 Answers
1
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>
);
}
Explanation
scrollerEl
is the scrollable container element. Make sure to set theoverflow
CSS property of this element toauto
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 thetrackedEl
, the callbackonScrollToElement
is invoked.scrollerEl.scrollTop
: number of pixels scrolled vertically. This is the scroll 'progress'. Before you scroll, the value is0
, 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 thetrackedEl
trackedEl.offsetTop
: The distance in pixel of thescrollerEl
top position to thetrackedEl
top position.trackedEl.offsetHeight
: The height oftrackedEl
including padding and border. This means you have to fully see thetrackedEl
beforeonScrollToElement
firesscrollerEl.offsetHeight
: The height ofscrollerEl
. Subtracting this because before you start scrolling, you've already seen the top part of the container.
Usage
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 theScroller
. If we track every elements insideScroller
, it will affect the performance in complex UI.onScrollToElement
: A callback that is executed when a tracked element is scrolled into view.
Live Demo

NearHuscarl
- 66,950
- 18
- 261
- 230
-
Sorry but it doesn't work. onScrollToElement return always false and i don't know why – Vali Talpas Apr 16 '21 at 13:13
-
Do you mean `onScrollToElement` is never called? Did you pass the `trackIds` list and adding an id to the button? @ValiTalpas – NearHuscarl Apr 16 '21 at 14:04
-
Yes. Should I use `
` in app.js? ` ` – Vali Talpas Apr 16 '21 at 15:11 -
Did you set `Scroller` overflow style to `auto` like in my example? @ValiTalpas – NearHuscarl Apr 16 '21 at 15:13
-
Yes, I don't know what I'm doing wrong :( – Vali Talpas Apr 16 '21 at 15:33
-
Can you add your codesandbox here so I can troubleshoot it? @ValiTalpas – NearHuscarl Apr 16 '21 at 15:34
-
https://codepen.io/talpasvali/project/editor/AjYbzE – Vali Talpas Apr 16 '21 at 15:38
-
@ValiTalpas all 3 buttons are in the viewport at the start, `Scroller` only detects if the button is inside the viewport while scrolling, you can use [this](https://stackoverflow.com/a/7557433/9449426) asnwer there to see if the button is in the viewport at the beginning and set its display accordingly. See [this](https://codesandbox.io/s/67105187material-ui-transition-when-scroll-forked-4xyp6?file=/demo.tsx) codesandbox. – NearHuscarl Apr 16 '21 at 16:06
-
In my visual studio code it's not at the beginning. It's ok, I appreciate your effort, I'll try to solve it somehow with your code – Vali Talpas Apr 16 '21 at 16:44