A Pen by Anisur Rahman on CodePen.
Created
May 7, 2018 06:43
-
-
Save anisur3036/9d97d55790d46ba9bbe0febb3f9c4c19 to your computer and use it in GitHub Desktop.
Smooth scrolling to anchor with pure javascript
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
<div class="container"> | |
<div class="filler anchor" id="anchor1">anchor1</div> | |
<div class="links"> | |
<a id="anchor1Link" href="#anchor1">Anchor 1</a> | |
<a id="anchor2Link" href="#anchor2">Anchor 2</a> | |
<a id="anchor3Link" href="#anchor3">Anchor 3</a> | |
<a id="anchor4Link" href="#anchor4">Anchor 4</a> | |
</div> | |
<div class="longText"> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p id="anchor2" class="anchor">anchor2 : This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p id="anchor3" class="anchor">anchor3 : This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p>This is a line, and there will be more after me.</p> | |
<p id="anchor4" class="anchor">anchor4 : This is a line, and there will be more after me.</p> | |
</div> | |
<div class="links"> | |
<a id="anchor1Link2" href="#anchor1">Anchor 1</a> | |
<a id="anchor2Link2" href="#anchor2">Anchor 2</a> | |
<a id="anchor3Link2" href="#anchor3">Anchor 3</a> | |
<a id="anchor4Link2" href="#anchor4">Anchor 4</a> | |
</div> | |
<div class="filler"></div> | |
</div> |
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() { | |
let d = document; | |
function init() { | |
//Links | |
let anchor1Link = d.getElementById('anchor1Link'); | |
let anchor2Link = d.getElementById('anchor2Link'); | |
let anchor3Link = d.getElementById('anchor3Link'); | |
let anchor4Link = d.getElementById('anchor4Link'); | |
let anchor1Link2 = d.getElementById('anchor1Link2'); | |
let anchor2Link2 = d.getElementById('anchor2Link2'); | |
let anchor3Link2 = d.getElementById('anchor3Link2'); | |
let anchor4Link2 = d.getElementById('anchor4Link2'); | |
//Anchors | |
let anchor1 = d.getElementById('anchor1'); | |
let anchor2 = d.getElementById('anchor2'); | |
let anchor3 = d.getElementById('anchor3'); | |
let anchor4 = d.getElementById('anchor4'); | |
anchor1Link.addEventListener('click', (e) => { scrollTo(anchor1, e) }, false); | |
anchor1Link2.addEventListener('click', (e) => { scrollTo(anchor1, e) }, false); | |
anchor2Link.addEventListener('click', (e) => { scrollTo(anchor2, e) }, false); | |
anchor2Link2.addEventListener('click', (e) => { scrollTo(anchor2, e) }, false); | |
// anchor2Link.onclick = function() { scrollToSimple(document.documentElement, 500, 3000); } | |
// anchor2Link2.onclick = function() { scrollToSimple(document.documentElement, 0, 3000); } | |
anchor3Link.addEventListener('click', (e) => { scrollTo(anchor3, e) }, false); | |
anchor3Link2.addEventListener('click', (e) => { scrollTo(anchor3, e) }, false); | |
anchor4Link.addEventListener('click', (e) => { scrollTo(anchor4.offsetTop, e) }, false); | |
anchor4Link2.addEventListener('click', (e) => { scrollTo(anchor4.offsetTop, e) }, false); | |
console.log(anchor2); //DEBUG | |
console.log('anchor1: '+scrollTopValue(anchor1)+' / '+offsetTopValue(anchor1)); //DEBUG | |
console.log('anchor2: '+scrollTopValue(anchor2)+' / '+offsetTopValue(anchor2)); //DEBUG | |
console.log('anchor3: '+scrollTopValue(anchor3)+' / '+offsetTopValue(anchor3)); //DEBUG | |
console.log('anchor4: '+scrollTopValue(anchor4)+' / '+offsetTopValue(anchor4)); //DEBUG | |
// d.addEventListener('scroll', (e) => { console.log(e) }, false); //DEBUG | |
console.log('App loaded. Have fun!'); | |
} | |
function scrollTopValue(domElement) { //DEBUG | |
return 'scrollTopValue:', domElement.scrollTop; | |
} | |
function offsetTopValue(domElement) { //DEBUG | |
return 'offsetTopValue:', domElement.offsetTop; | |
} | |
/*function scrollToSimple(element, to, duration) { //FIXME finish this | |
if (duration < 0) return; | |
var difference = to - element.offsetTop; | |
var perTick = difference / duration * 10; | |
console.log('perTick', perTick); //DEBUG | |
setTimeout(function() { | |
console.log('element.scrollTop:', element.scrollTop); //DEBUG | |
element.scrollTop += perTick; | |
console.log('element.scrollTop:', element.scrollTop); //DEBUG | |
scrollTo(element, to, duration - 10); | |
}, 10); | |
}*/ | |
//cf. https://gist.github.com/james2doyle/5694700 | |
// requestAnimationFrame for Smart Animating https://goo.gl/sx5sts | |
var requestAnimFrame = (function() { | |
return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function(callback) { | |
window.setTimeout(callback, 1000 / 60); | |
}; | |
})(); | |
function scrollTo(to, callback, duration = 1500) { //FIXME this always starts from '0', instead of the clicked element offsetTop -> This is because the position is calculated for the main <html> element, not the <iframe>'s <html> tag | |
/*console.log('from:', from); //DEBUG | |
// console.log('from.clientY:', from.clientY); //DEBUG | |
// console.log('from.target.offsetTop:', from.target.offsetTop); //DEBUG | |
// console.log('position():', document.documentElement.offsetTop || document.body.parentNode.offsetTop || document.body.offsetTop); //DEBUG | |
// console.log('document.documentElement:', document.documentElement); //DEBUG | |
// console.log('document.body:', document.body); //DEBUG | |
let start; | |
if (isMouseEvent(from)) { //FIXME : the scroll starts at the link, not where the screen really is : fix that | |
// start = from.target.offsetTop; | |
start = from.pageY; //FIXME | |
} | |
else { | |
start = from; | |
}*/ | |
if (isDomElement(to)) { | |
// console.log('this is an element:', to); //DEBUG | |
to = to.offsetTop; | |
} | |
/*else { | |
// console.log('this is NOT an element:', to); //DEBUG | |
}*/ | |
// because it's so fucking difficult to detect the scrolling element, just move them all | |
function move(amount) { | |
// document.scrollingElement.scrollTop = amount; //FIXME Test that | |
document.documentElement.scrollTop = amount; | |
document.body.parentNode.scrollTop = amount; | |
document.body.scrollTop = amount; | |
} | |
function position() { | |
return document.documentElement.offsetTop || document.body.parentNode.offsetTop || document.body.offsetTop; | |
} | |
var start = position(), | |
change = to - start, | |
currentTime = 0, | |
increment = 20; | |
console.log('start:', start); //DEBUG | |
console.log('to:', to); //DEBUG | |
console.log('change:', change); //DEBUG | |
var animateScroll = function() { | |
// increment the time | |
currentTime += increment; | |
// find the value with the quadratic in-out easing function | |
var val = Math.easeInOutQuad(currentTime, start, change, duration); | |
// move the document.body | |
move(val); | |
// do the animation unless its over | |
if (currentTime < duration) { | |
requestAnimFrame(animateScroll); | |
} | |
else { | |
if (callback && typeof(callback) === 'function') { | |
// the animation is done so lets callback | |
callback(); | |
} | |
} | |
}; | |
animateScroll(); | |
} | |
init(); | |
})(); | |
//-------------------- Unimportant js functions -------------------- | |
// easing functions https://goo.gl/5HLl8 | |
//t = current time | |
//b = start value | |
//c = change in value | |
//d = duration | |
Math.easeInOutQuad = function(t, b, c, d) { | |
t /= d / 2; | |
if (t < 1) { | |
return c / 2 * t * t + b | |
} | |
t--; | |
return -c / 2 * (t * (t - 2) - 1) + b; | |
}; | |
Math.easeInCubic = function(t, b, c, d) { | |
var tc = (t /= d) * t * t; | |
return b + c * (tc); | |
}; | |
Math.inOutQuintic = function(t, b, c, d) { | |
var ts = (t /= d) * t, | |
tc = ts * t; | |
return b + c * (6 * tc * ts + -15 * ts * ts + 10 * tc); | |
}; | |
function isDomElement(obj) { | |
return obj instanceof Element; | |
} | |
function isMouseEvent(obj) { | |
return obj instanceof MouseEvent; | |
} | |
function findScrollingElement(element) { //FIXME Test this too | |
do { | |
if (element.clientHeight < element.scrollHeight || element.clientWidth < element.scrollWidth) { | |
return element; | |
} | |
} while (element = element.parentNode); | |
} |
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
.links { | |
// position: absolute; | |
// top: 0; | |
// left: 50%; | |
// transform: translate(-50%, 0); | |
margin-top: 0.5rem; | |
margin-bottom: 2rem; | |
a { | |
font-size: 1.4rem; | |
color: lightblue; | |
text-decoration: none; | |
transition: color .5s ease, border-bottom .5s ease; | |
border-bottom: 2px solid transparent; | |
&:hover { | |
color: yellow; | |
border-bottom: 2px solid yellow; | |
} | |
&:not(:last-of-type) { | |
margin-right: 2rem; | |
} | |
} | |
} | |
.longText { | |
& > p:last-of-type:after { | |
content : '...or not ;)'; | |
} | |
} | |
.anchor { | |
color: lime; | |
font-weight: bold; | |
} | |
p { | |
margin: 0; | |
text-align: center; | |
} | |
//-------------------- Unimportant css rules -------------------- | |
$transitionDuration: 0.3s; | |
.container { | |
// height: 100vh; | |
display: flex; | |
flex-direction: column; | |
justify-content: center; | |
align-items: center; | |
} | |
.filler { | |
background-color : #0B3553; | |
border: 1px solid #022238; | |
opacity : 0.80; | |
height: 25vh; | |
width: 99vw; //FIXME: 100vw make a scrollbar appear :'( | |
} | |
body { | |
background: #333; //#022238 | |
color: white; | |
font-family: "Open sans", sans-serif; | |
font-weight: 100; | |
font-size: 1rem; | |
} | |
a.button { | |
// color: white; | |
color: yellow; | |
text-decoration: none; | |
transition: color $transitionDuration ease; | |
&:focus { | |
outline: none; | |
} | |
&:hover { | |
// color: deeppink; | |
color: lime; | |
} | |
} | |
.button2 { | |
background-color : deeppink; | |
color : white; | |
border : 1px solid red; | |
border-radius : 2px; | |
height : 30px; | |
cursor : pointer; | |
outline : none; | |
&:focus, &:active { | |
outline : none; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment