Skip to content

Instantly share code, notes, and snippets.

@tsmd
Last active October 27, 2018 17:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tsmd/5dd8ddfe6c6b233bd68a6636bffac6f3 to your computer and use it in GitHub Desktop.
Save tsmd/5dd8ddfe6c6b233bd68a6636bffac6f3 to your computer and use it in GitHub Desktop.
FLIP implementation of smooth scrolling supporting some fixed elements
.smooth-scroll {
transition: transform 0.5s ease-out !important;
}
.smooth-scroll-fixed {
display: none !important;
}
var getFixedElements = function () {
var all = document.querySelectorAll('*')
return Array.prototype.filter.call(all, function (el) {
return getComputedStyle(el).position === 'fixed'
})
}
var getMovableElements = function (fixedElements) {
var bodyChildren = document.body.children
return Array.prototype.filter.call(bodyChildren, function (el) {
return fixedElements.indexOf(el) === -1
})
}
var prepareDummies = function (fixedElements) {
return fixedElements.map(function (fixed) {
var dummy = fixed.cloneNode(true)
fixed.classList.add('smooth-scroll-fixed')
dummy.classList.add('smooth-scroll-dummy')
document.body.appendChild(dummy)
return dummy
})
}
var destroyDummies = function (fixedElements, dummies) {
fixedElements.forEach(function (fixed) {
fixed.classList.remove('smooth-scroll-fixed')
})
dummies.forEach(function (dummy) {
document.body.removeChild(dummy)
})
}
var handleClick = function () {
var pageXOffset = window.pageXOffset
var pageYOffset = window.pageYOffset
var fixedElements = getFixedElements()
var movablesElements = getMovableElements(fixedElements)
if (!movablesElements.length) {
return
}
var dummies = prepareDummies(fixedElements)
requestAnimationFrame(function () {
var scrollXOffset = window.pageXOffset - pageXOffset
var scrollYOffset = window.pageYOffset - pageYOffset
if (scrollXOffset === 0 && scrollYOffset === 0) {
destroyDummies(fixedElements, dummies)
return
}
movablesElements.forEach(function (el) {
el.style.transform = 'translate(' + scrollXOffset + 'px, ' + scrollYOffset + 'px)'
})
requestAnimationFrame(function () {
movablesElements.forEach(function (el) {
el.classList.add('smooth-scroll')
el.style.transform = 'translate(0px, 0px)'
})
})
movablesElements[0].addEventListener('transitionend', function reset(e) {
if (e.target !== movablesElements[0]) {
return
}
destroyDummies(fixedElements, dummies)
movablesElements.forEach(function (el) {
el.classList.remove('smooth-scroll')
el.style.transform = ''
})
movablesElements[0].removeEventListener('transitionend', reset)
}, false)
})
}
document.addEventListener('DOMContentLoaded', function () {
var anchors = document.querySelectorAll('a[href^="#"]')
Array.prototype.forEach.call(anchors, function (anchor) {
anchor.addEventListener('click', handleClick)
})
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment