Scrolling to an anchor given fixed position navbar
by ianclark001
HTML
<div id="fixed">
My fixed 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;
}
#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'),...