Created
August 16, 2016 22:21
-
-
Save mikeobrien/e07bf6a8d8a1c78c95cc247421a93433 to your computer and use it in GitHub Desktop.
Sticky headers
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
+function ($) { | |
var currentHeader = null; | |
var animating = false; | |
$(document).scroll(function() { | |
if (animating) return; | |
animating = true; | |
requestAnimationFrame(animateHeader); | |
animating = false; | |
}); | |
function animateHeader() { | |
if (currentHeader) { | |
var stickyHeader = getHeaderDescriptor(currentHeader); | |
if (stickyHeader.parent.top >= 0 || | |
stickyHeader.parent.bottom < 0) | |
{ | |
stickyHeader.element.remove(); | |
currentHeader = null; | |
// Animate once more in case another header | |
// is now active otherwise it will be skipped. | |
animateHeader(); | |
} | |
else if (stickyHeader.bottom >= stickyHeader.height && | |
stickyHeader.element.css('position') == 'absolute') | |
{ | |
stickyHeader.element.css({ | |
top: 0, | |
position: 'fixed', | |
'margin-top': '0' | |
}); | |
} | |
else if (stickyHeader.bottom >= stickyHeader.parent.bottom) | |
{ | |
stickyHeader.element.css({ | |
position:'absolute', | |
top: $('body').scrollTop() - | |
(stickyHeader.height - | |
stickyHeader.parent.bottom) | |
}); | |
} | |
return; | |
} | |
var header = findHeader(); | |
if (!header || header.height == header.parent.height) return; | |
if (header.parent.bottom <= header.height) | |
{ | |
var top = $('body').scrollTop() - | |
(header.height - header.parent.bottom); | |
currentHeader = createStickyHeader(header, top, 'absolute'); | |
} | |
else | |
{ | |
currentHeader = createStickyHeader(header, 0, 'fixed'); | |
} | |
} | |
function createStickyHeader(header, top, position) { | |
var stickyHeader = header.element.clone(); | |
stickyHeader.hide(); | |
header.parent.element.append(stickyHeader); | |
stickyHeader.css({ | |
top: top, | |
left: header.left, | |
width: header.width, | |
height: header.height, | |
position: position, | |
'margin-top': '0' | |
}); | |
stickyHeader.show(); | |
return stickyHeader; | |
} | |
function findHeader() { | |
return _.chain($('div.sticky')) | |
.map(getHeaderDescriptor) | |
.findLast(function(x) { | |
return x.top <= 0 && x.parent.bottom > 0; | |
}) | |
.value(); | |
} | |
function getHeaderDescriptor(element) { | |
var header = element instanceof jQuery ? element : $(element); | |
element = element instanceof jQuery ? element[0] : element; | |
var parent = header.parent(); | |
var coords = element.getBoundingClientRect(); | |
var parentCoords = element.parentElement.getBoundingClientRect(); | |
return { | |
parent: { | |
left: parentCoords.left, | |
right: parentCoords.right, | |
top: parentCoords.top, | |
bottom: parentCoords.bottom, | |
width: parent.width(), | |
height: parent.height(), | |
element: parent | |
}, | |
left: coords.left, | |
right: coords.right, | |
top: coords.top, | |
bottom: coords.bottom, | |
width: header.width(), | |
height: header.height(), | |
element: header | |
}; | |
} | |
}(jQuery); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment