Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Keep headroom pinned when navigating to an internal link #126

Open
kripod opened this issue Dec 24, 2017 · 0 comments
Open

Keep headroom pinned when navigating to an internal link #126

kripod opened this issue Dec 24, 2017 · 0 comments

Comments

@kripod
Copy link

kripod commented Dec 24, 2017

When navigating to an internal link of a page (e.g. #something), I think that the headroom should always be shown until the scrolling ends. The reason behind this is that elements with IDs are usually positioned to accommodate a fixed header above themselves. Pinning the headroom during a programmatically invoked scroll would also improve consistency with the proposed non-JS mode (please see #125 for further details).

Also, in order to support smooth scrolling behavior, continuous inspection of window.pageYOffset is required. I wrote the following code snippet to solve the aforementioned problems:

const SCROLL_MAX_FRAMES_WITHOUT_PAGE_OFFSET_CHANGE = 30;

class Headroom extends React.Component {
  constructor() {
    // ...

    this.setState({
      downTolerance: this.props.downTolerance,
    });

    // Avoid problems with server-side rendering
    if (typeof window !== 'undefined') {
      // Keep headroom pinned during smooth scroll
      window.addEventListener('hashchange', () => {
        // Disable headroom unpinning caused by scrolling downwards
        this.setState({ downTolerance: Number.POSITIVE_INFINITY });
        this.headroom.pin();

        // Re-enable headroom unpinning after smooth scroll
        let prevPageYOffset = window.pageYOffset;
        let framesWithoutPageOffsetChange = 0;
        const checkScrollState = () => {
          // Check whether scrolling is still in progress
          if (window.pageYOffset !== prevPageYOffset) {
            prevPageYOffset = window.pageYOffset;
            framesWithoutPageOffsetChange = 0;
          } else {
            framesWithoutPageOffsetChange += 1;
            if (framesWithoutPageOffsetChange > SCROLL_MAX_FRAMES_WITHOUT_PAGE_OFFSET_CHANGE) {
              // Restore downTolerance of the headroom
              this.setState({ downTolerance: this.props.downTolerance });
              return;
            }
          }

          raf(checkScrollState);
        };

        raf(checkScrollState);
      });
    }
  }
}

A customized implementation of the snippet can be found here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant