Last active
April 6, 2024 16:18
-
-
Save Kernix13/cf24e4390c72c0dc0e5ccb30c277d843 to your computer and use it in GitHub Desktop.
Back To Top Button
This file contains hidden or 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
<!-- Simpler version on my portfolio site: | |
https://jameskernicky.netlify.app/ | |
https://github.com/Kernix13/personal-portfolio | |
--> | |
<button id="back-to-top-btn"><i class="fa-solid fa-angle-up"></i></button> | |
<!-- Bootstrap icon instead of font awesome --> | |
<svg | |
xmlns="http://www.w3.org/2000/svg" | |
width="16" | |
height="16" | |
fill="currentColor" | |
class="bi bi-chevron-up" | |
viewBox="0 0 16 16" | |
> | |
<path | |
fill-rule="evenodd" | |
d="M7.646 4.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1-.708.708L8 5.707l-5.646 5.647a.5.5 0 0 1-.708-.708z" | |
/> | |
</svg> |
This file contains hidden or 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
const backToTopButton = document.querySelector('#back-to-top-btn'); | |
window.addEventListener('scroll', scrollFunction); | |
/** | |
* Display or hide back-to-top btn based on scrollY | |
*/ | |
function scrollFunction() { | |
if (window.scrollY > 300) { | |
// Show backToTopButton | |
if (!backToTopButton.classList.contains('btnEntrance')) { | |
backToTopButton.classList.remove('btnExit'); | |
backToTopButton.classList.add('btnEntrance'); | |
backToTopButton.style.display = 'block'; | |
} | |
} else { | |
// Hide backToTopButton | |
if (backToTopButton.classList.contains('btnEntrance')) { | |
backToTopButton.classList.remove('btnEntrance'); | |
backToTopButton.classList.add('btnExit'); | |
setTimeout(function () { | |
backToTopButton.style.display = 'none'; | |
}, 125); | |
} | |
} | |
} | |
backToTopButton.addEventListener('click', smoothScrollBackToTop); | |
/** | |
* Control scroll animation | |
*/ | |
function smoothScrollBackToTop() { | |
const duration = 1250; | |
let start = null; | |
const startPosition = window.scrollY; | |
const distanceToTop = -1 * startPosition; | |
window.requestAnimationFrame(step); | |
/** | |
* Synchronize animation using timestamp | |
* @param {milliseconds} timestamp | |
*/ | |
function step(timestamp) { | |
if (!start) start = timestamp; | |
const progress = timestamp - start; | |
window.scrollTo( | |
0, | |
easeInOutCubic(progress, startPosition, distanceToTop, duration) | |
); | |
if (progress < duration) window.requestAnimationFrame(step); | |
} | |
} | |
/** | |
* | |
* Cubic-bezier function for scroll animation | |
* | |
* @param {milliseconds} prog | |
* @param {pixels} startPos | |
* @param {pixels} dist | |
* @param {milliseconds} dur | |
* @returns | |
*/ | |
function easeInOutCubic(prog, startPos, dist, dur) { | |
prog /= dur / 2; | |
if (prog < 1) { | |
return (dist / 2) * prog * prog * prog + startPos; | |
} | |
prog -= 2; | |
return (dist / 2) * (prog * prog * prog + 2) + startPos; | |
} |
This file contains hidden or 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
.fa-solid { | |
font-size: 2rem; | |
padding-bottom: 0.5em; | |
} | |
.fa-angle-up { | |
color: #fff; | |
} | |
#back-to-top-btn { | |
display: none; | |
position: fixed; | |
font-size: 18px; | |
width: 44px; | |
height: 44px; | |
bottom: 10px; | |
left: 10px; | |
font-weight: bolder; | |
border: none; | |
outline: none; | |
background-color: rgba(0, 0, 0, 0.4); | |
color: white; | |
cursor: pointer; | |
padding: 0.25em 0.5em; | |
border-radius: 0.25em; | |
transition-duration: 100ms; | |
transition-timing-function: ease-in-out; | |
transition-property: background-color, color; | |
z-index: 999; | |
} | |
#back-to-top-btn:hover, | |
#back-to-top-btn:focus { | |
background-color: rgba(0, 0, 0, 0.8); | |
color: #fff; | |
} | |
/* Animations */ | |
.btnEntrance { | |
animation-duration: 0.5s; | |
animation-fill-mode: both; | |
animation-name: btnEntrance; | |
} | |
/* fadeInUp */ | |
@keyframes btnEntrance { | |
from { | |
opacity: 0; | |
transform: translate3d(0, 100%, 0); | |
} | |
to { | |
opacity: 1; | |
transform: translate3d(0, 0, 0); | |
} | |
} | |
.btnExit { | |
animation-duration: 0.25s; | |
animation-fill-mode: both; | |
animation-name: btnExit; | |
} | |
/* fadeOutDown */ | |
@keyframes btnExit { | |
from { | |
opacity: 1; | |
} | |
to { | |
opacity: 0; | |
transform: translate3d(0, 100%, 0); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment