Search code examples
javascriptcssreactjssticky

Jumpy Nav bar upon changing height (sticky property)


I'm having a strange problem that I dont know how to deal with.

I basically want to decrease the size of my navbar when the user starts scrolling down the page but due to this change of height, the navbar makes a jumpy effect and if the page's height is 100% of the available space + a slight scroll, the navbar gets kinda stuck in between two states. Problem illustrated at the bottom.

I have tried programically scrolling the page before setting scrolled state to true to prevent the navbar from resizing but that was horrible.

This is my window.onscroll event:

  handleScroll = () => {
    const { scrolled } = this.state;
    console.log(window.scrollY, window.pageYOffset);
    if (window.pageYOffset >= 10 && !scrolled) {
      this.setState({ scrolled: true });
    } else if (window.pageYOffset == 0 && scrolled) {
      this.setState({ scrolled: false });
    }
  };

and this is my css:

nav {
  height: 150px;
  background: black;
  color: white;
  transition: all 0.2s ease-in;
  position: sticky;
}

nav.scrolled {
  height: 80px;
}

enter image description here


Solution

  • I had a similar challenge, where I wanted to move the navigation from a static position to a fixed. So the navigation is at a static position on the page, and as soon the user reaches a breakpoint, the navigation would change into a fixed position, so that it is always visible and at the top of the screen. further more, the height changed too.

    the solution I had for this, as the main problem is the change in the overall page height, to add a placeholder element with the exact height of the navigation, and show it as soon as the navigation gets sticky.

    So the solution is, just to ensure, the overall height does not change.

    For example, if you would change your css to this, you should not be seeing this effect (not my suggested solution!), as you would not change the overall height, and therefore you would not trigger multiple scroll and rerender issues:

    nav {
      height: 150px;
      padding-bottom: 0;
      background: black;
      color: white;
      transition: all 0.2s ease-in;
      position: sticky;
    }
    
    nav.scrolled {
      height: 80px;
      padding-bottom: 70px;
    }
    

    you could get better insights, if you placed some console.log when toggeling the state of scrolled.