javascript - How to detect automatic scrolling to anchors? -


i have 1 page website, example.com. there 2 sections: intro @ top of page, , contact @ bottom of page. if want visit contact section without having scroll through intro, give them link: example.com/#contact. i'm talking these visits below.

the browser automatically scrolls down contact section, ignores fixed navigation @ top of page, contact section scrolled behind navigation top of contact section becomes invisible. want correct using javascript, subtracting height of fixed navigation scroll position. let's call function scrollcorrector. problem don't know when such automatic scrolling happens, scrollcorrector isn't called everytime should be.

when should scrollcorrector called? when automatic scrolling happens because of hash portion. why not use onscroll? because way can't differenciate auto scroll user scroll. why not use onclick on every <a href="example.com/#contact">? i'll use it, if user navigates browser's button? okay, i'll use onpopstate well. if user comes example.com/#intro manually rewriting url example.com/#contact? okay, i'll use onhashchange well. if user on example.com/#contact, clicks address bar, , presses enter without modification? none of above helps then.

what event should listen then? if such event doesn't exist, how scrollcorrector know automatic scroll has happened?

the scroll event fire, could,

  • check actual location.hash, if empty don't care
  • debounce event sure it's not mousewheel triggered it
  • get actual document.queryselector(location.hash).getboundingclientrect().top, if ===0 call scrollcorrector.

var anchorscroller = function() {    // variable keep track of last scroll event    var last = -100, // set -100 first call (on page load) understood anchor call      // variable keep our debounce timeout can cancel further      timeout;      this.debounce = function(e) {      // first check if we've got hash set, if last call scroll made more 100ms ago      if (location.hash !== '' && performance.now() - last > 100)      // if so, set timeout sure there no other scroll coming        timeout = settimeout(shouldfire, 100);      // that's not anchor scroll, stop right !	      else cleartimeout(timeout);      // set new timestamp      last = performance.now();    }      function shouldfire() {      // pointer our anchored element      var el = document.queryselector(window.location.hash);      // if non-null (an other usage of location.hash) , @ top of our viewport      if (el && el.getboundingclientrect().top === 0) {        // anchor scroll        window.scrollto(0, window.pageyoffset - 64);      }    }  };  window.onscroll = new anchorscroller().debounce;
body {    margin: 64px 0 0 0;  }  nav {    background: blue;    opacity: 0.7;    position: fixed;    top: 0;    width: 100%;  }  {    color: #fff;    float: left;    font-size: 30px;    height: 64px;    line-height: 64px;    text-align: center;    text-decoration: none;    width: 50%;  }  div {    background: grey;    border-top: 5px #0f0 dashed;    font-size: 30px;    padding: 25vh 0;    text-align: center;  }  #intro,#contact {  background: red;}
<nav>    <a href="#intro">intro</a>    <a href="#contact">contact</a>  </nav>  <div id="intro">  intro </div>  <div> lorem </div>  <div id="contact">  contact </div>  <div> ipsum </div>

caveats :
- introduces 100ms timeout between scroll event , correction, visible.
- it's not 100% bullet-proof, user trigger 1 event (by mousewheel or keyboard) , fall @ right position produces false-positive. chances happen small might acceptable such behaviour.


Comments

Popular posts from this blog

resizing Telegram inline keyboard -

command line - How can a Python program background itself? -

php - "cURL error 28: Resolving timed out" on Wordpress on Azure App Service on Linux -