javascript - How to create an animated smooth sticky header in react - Stack Overflow

I have a header that I'd like to turn into a sticky header once the user starts scrolling down the

I have a header that I'd like to turn into a sticky header once the user starts scrolling down the page, it should also be smooth and not just jump down the screen and I don't want to just use a position: fixed to just stick it to the top of the screen. This is also in a nextjs application.

const Header = () => {
  useEffect(() => {
    window.onscroll = () => {
      document.getElementById('header').classList.add('sticky')

      // what else do I need here
    }
  }, [])
}

...

#header {
  transition: top 1s;
}

#header.sticky {
  position: sticky;

  // what else do I need here
}

I have a header that I'd like to turn into a sticky header once the user starts scrolling down the page, it should also be smooth and not just jump down the screen and I don't want to just use a position: fixed to just stick it to the top of the screen. This is also in a nextjs application.

const Header = () => {
  useEffect(() => {
    window.onscroll = () => {
      document.getElementById('header').classList.add('sticky')

      // what else do I need here
    }
  }, [])
}

...

#header {
  transition: top 1s;
}

#header.sticky {
  position: sticky;

  // what else do I need here
}
Share Improve this question edited Nov 3, 2021 at 11:39 asked Aug 4, 2021 at 12:17 user16435030user16435030 1
  • with position sticky, you don't need to add the class - you should just start with it and it will stick when it scrolls past the point you want it to stick - developer.mozilla/en-US/docs/Web/CSS/position – Pete Commented Aug 4, 2021 at 12:20
Add a ment  | 

2 Answers 2

Reset to default 4

There's a couple of things you'll need to do it.

let timeout
let scroll = 0

const Header = () => {
  useEffect(() => {
    window.onscroll = () => {
      if (timeout) {
        clearTimeout(timeout)
      }

      timeout = setTimeout(() => {
        if (scroll >= window.scrollY && window.scrollY > 10) {
          document.getElementById('header').classList.add('sticky')
        } else {
          document.getElementById('header').classList.remove('sticky')
        }

        scroll = window.scrollY
      }, 10)
    }
  }, [])
}

...

#header {
  top: -100px;
  transition: top 0.5s ease-in-out;
}

#header.sticky {
  position: sticky;
  top: 0;
}
  • Create a window event listener on scroll, use useEffect if it's a server side rendered application like in nextjs, otherwise you can leave that.
  • Assign or remove the sticky class on scroll, you can do this with document.getElementById or by using useRef on the header ponent.
  • Use a timeout so that the event isn't fired on every single scroll, instead it should fire only 10ms after the scrolling stopped.
  • Keep track of the scroll variable so that you can figure out if the user is scrolling up or down, that way you can display the header only if they're scrolling up.
  • As a little trick you can set the initial header position top to -100px, which will have no effect if there isn't actually any position: absolute, position: fixed or position: sticky on the header. Then when you apply the class sticky you change the top value to 0, which will create an effect where the header is suddenly "appearing" from the top once you scroll down. This is what's creating the animation.

The self-answered solution seems like so much more work than is necessary; a pure CSS solution should be sufficient, unless I'm misunderstanding the requirements. See below:

const Header = () => {
  return (
    <div className="header">header content here</div>
  );
};


const Content = () => {
  return (
    <div className="content">
      <h1>Hello</h1>
      <p>How are you?</p>
      <p>Lovely weather were having, no?</p>
      <p>The quick brown fox jumped over the lazy dog</p>
      <p>Every Good Boy Does Fine</p>
      <p>Mary's violet eyes made john stay up nights proposing</p>
      <p>FOIL</p>
      <p>How are you?</p>
      <p>Lovely weather were having, no?</p>
      <p>The quick brown fox jumped over the lazy dog</p>
      <p>Every Good Boy Does Fine</p>
      <p>Mary's violet eyes made john stay up nights proposing</p>
      <p>FOIL</p>
      <p>How are you?</p>
      <p>Lovely weather were having, no?</p>
      <p>The quick brown fox jumped over the lazy dog</p>
      <p>Every Good Boy Does Fine</p>
      <p>Mary's violet eyes made john stay up nights proposing</p>
      <p>FOIL</p>
    </div>
  );
};

const App = () => {
  return (
    <div>
      <Header />
      <Content />
    </div>
  );
};

// Render it
ReactDOM.render(
  <App />,
  document.getElementById("react")
);
body {
  padding: 0;
  margin: 0;
}

.header {
  background-color: pink;
  padding: 1rem;
  position: sticky;
  top: 0;
}
<script src="https://cdnjs.cloudflare./ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="react"></div>

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744266752a4565902.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信