JS: Jump to an anchor when have a fixed position navbar

Uses vanilla JavaScript. On a site with a fixed header, and on-page anchor tag links, JS is used to correctly align the top of the anchored content to the bottom of the fixed header. No jank, no hidden content.

by Sheryl Hohman

HTML

<div id="fixed">
  My fixed header bar
</div>

<div id="targets">
  <div id="target-1">
    <a href="#target-2">Jump to target 2</a>
  </div>
  <div id="target-2">
    <a href="#target-3">Jump to target 3</a>
  </div>
  <div id="target-3">
    <a href="#target-4">Jump to target 4</a>
  </div>
  <div id="target-4">
    <a href="#target-5">Jump to target 5</a>
  </div>
  <div id="target-5">
    <a href="#target-1">Jump to target 1</a>
  </div>
</div>

CSS

body {
  padding: 0;
  margin: 50px 0 0;
  font-family: "Arial";
  font-size: 1em;
}

a {
  color: #333;
}

#fixed {
  position: fixed;
  height: 50px;
  line-height: 50px;
  background: #000;
  top: 0;
  left: 0;
  right: 0;
  color: #fff;
  padding-left: 5px;
}

/* */
#targets div {
  height: 100vh;
  padding: 10px;
  color: #333;
}
/* */
/* This version, only 2 of the anchors work * /
#targets div {
  height: 15vh;
  padding: 10px;
  color: #666;
}
/* */

#target-1 {
  background: #888;
}

#target-2 {
  background: #999;
}

#target-3 {
  background: #AAA;
}

#target-4 {
  background: #BBB;
}

#target-5 {
  background: #CCC;
}

JavaScript

(function(document, history, location) {
  var HISTORY_SUPPORT = !!(history && history.pushState);

  var anchorScrolls = {
    ANCHOR_REGEX: /^#[^ ]+$/,
    OFFSET_HEIGHT_PX: 50,

    /**
     * Establish events, and fix initial scroll position if a hash is provided.
     */
    init: function() {
      this.scrollToCurrent();
      window.addEventListener('hashchange', this.scrollToCurrent.bind(this));
      document.body.addEventListener('click', this.delegateAnchors.bind(this));
    },

    /**
     * Return the offset amount to deduct from the normal scroll position.
     * Modify as appropriate to allow for dynamic calculations
     */
    getFixedOffset: function() {
      return this.OFFSET_HEIGHT_PX;
    },

    /**
     * If the provided href is an anchor which resolves to an element on the
     * page, scroll to it.
     * @param  {String} href
     * @return {Boolean} - Was the href an anchor.
     */
    scrollIfAnchor: function(href, pushToHistory) {
      var match, rect, anchorOffset;

      if(!this.ANCHOR_REGEX.test(href)) {
        return false;
      }

      match = document.getElementById(href.slice(1));

      if(match) {
        rect = match.getBoundingClientRect();
        anchorOffset = window.pageYOffset + rect.top - this.getFixedOffset();
        window.scrollTo(window.pageXOffset, anchorOffset);

        // Add the state to history as-per normal anchor links
        if(HISTORY_SUPPORT && pushToHistory) {
          history.pushState({}, document.title, location.pathname + href);
        }
      }

      return !!match;
    },

    /**
     * Attempt to scroll to the current location's hash.
     */
    scrollToCurrent: function() {
      this.scrollIfAnchor(window.location.hash);
    },

    /**
     * If the click event's target was an anchor, fix the scroll position.
     */
    delegateAnchors: function(e) {
      var elem = e.target;

      if(
        elem.nodeName === 'A' &&
        this.scrollIfAnchor(elem.getAttribute('href'),...