loading...
Cover image for React: Hiding an Element as you Scroll

React: Hiding an Element as you Scroll

lukekyl profile image Kyle Luke ・3 min read

Recently I was looking for a way to hide (or possibly show) an element as you scroll down the page in my React app (portfolio site). YES, there are some React components that you can add on that may do the trick depending on the task (see React-Headroom), but this guide is meant to give you the run-down on how to enable this feature in a React component for yourself. After taking a quick look at the example below (the social media icons appear and disappear), lets get down to business.

Example from kyleluke.dev

Setting State

state = {
    opacity: '1'
}

First, the state will need to be set to the base value you are wanting your feature to have. State for this feature will be the css values that you will want to change. Are you wanting it to appear, or disappear (where would you like the state to start)? Are you wanting it to slide in and out (top, right, bottom, or left positions), or fade in and out (opacity)?

From here, we will be able to adjust the state based on the transition we would like to see, and the timing of that transition while scrolling the page.

Timing the Transition

componentDidMount() {
    if (typeof window !== "undefined") {
      window.onscroll = () => {
        let currentScrollPos = window.pageYOffset;
        let maxScroll = document.body.scrollHeight - window.innerHeight;
        // console.log(maxScroll)
        if (currentScrollPos > 0 && currentScrollPos < maxScroll) {
          this.setState({ opacity: "0" })
          // console.log(currentScrollPos)
        } else {
          this.setState({ opacity: "1" })
        }
      }
    }
  }

As the component mounts, we will start watching the window for an onscroll event. You will first create a currentScrollPos variable, and then work with your desired scroll location for the state to change.

This example is set to watch for a scroll position of 0 (top of the page), and the scroll position when the user scrolls to bottom of the page, or its maxScroll position (total scroll height - window height = user has scrolled as far down as they can).

This part can be the most tricky, as you want to do the math as to where your desired scroll location will be for the transition to happen. Think about the window height along with the body height, as you will not be able to scroll the entire body height. You will find example console.log() variables that you may want to watch while troubleshooting your own component.

Updating State for Transition

if (currentScrollPos > 0 && currentScrollPos < maxScroll) {
        this.setState({ opacity: "0" })
    } 
else {
        this.setState({ opacity: "1" })
    }

Performing the transition is as easy as updating state. You might be setting the opacity to change, you might be moving the position from -5rem to 0 (or vice versa). This is where you can tinker with a variety of CSS properties and values to perform the transition you are going for.

Declaring the Element

render() {
    return (
        <div className="your-class" style={{ opacity: `${this.state.opacity}`}} >
        {/* additonal content */}
        </div>
    )
}

Here we declare the element in the return value within the component you are working with. Here you would adjust the style you are transitioning, in this case we are working with opacity. You are able to transition multiple styles with this technique.

Additional CSS that may be helpful

.your-class {
    z-index:200;
    position: fixed;
    bottom:0;  // this can be used to transition a sliding effect. Try -5rem in initial state
    transition: opacity .1s ease;  // this allows for a smooth transition effect
}

The styling here is highly specialized for your select case, but I wanted to include some ideas you might think about as supplements to your transition. Particularly the CSS property: transition. It has many features that can make your transition perform in a much nicer looking way.

Full Component

import React, { Component } from 'react';

class Index extends Component {
  state = {
    opacity: '1'
  }

  componentDidMount() {
    if (typeof window !== "undefined") {
      window.onscroll = () => {
        let currentScrollPos = window.pageYOffset;
        let maxScroll = document.body.scrollHeight - window.innerHeight;
        // console.log(maxScroll)
        if (currentScrollPos > 0 && currentScrollPos < maxScroll) {
          this.setState({ opacity: "0" })
          // console.log(currentScrollPos)
        } else {
          this.setState({ opacity: "1" })
        }
      }
    }
  }

  render() {
    return (
        <div className="your-class" style={{ opacity: `${this.state.opacity}`}} >
         {/* additonal content */} Hello World
        </div>
    )
  }
}

export default Index

Here is the complete component with all of the steps put together. Hopefully this helps visualize what steps are required to hide/show an element in a particular zoom location in your app!

Please leave comments if you found this useful, and any improvements you have made in your own app!

Posted on by:

lukekyl profile

Kyle Luke

@lukekyl

Designer turned Developer in Denver

Discussion

pic
Editor guide
 

Will there be any performance issue when setting the opacity to 0 if you are trying to create an infinite list of element to scroll?

 

I honestly haven't had the chance to play with infinite scroll on my own yet, but it looks like you may want to use a transformation based on when the scroll function loads more items. See this post on stackoverflow for one solution: Isotope's Masonry Infinite Scroll Solution