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
- scrollerElis the scrollable container element. Make sure to set the- overflowCSS property of this element to- autoto show the scrollbar when there is not enough space.
- trackedElis the child element inside the scrollable container to keep track of, when the user scrolls to the- trackedEl, the callback- onScrollToElementis 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- scrollerEltop position to the- trackedEltop position.
- trackedEl.offsetHeight: The height of- trackedElincluding padding and border. This means you have to fully see the- trackedElbefore- onScrollToElementfires
- scrollerEl.offsetHeight: The height of- scrollerEl. 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 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.
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
