Skip to content

Instantly share code, notes, and snippets.

@bibek-magar
Last active April 4, 2024 04:13
Show Gist options
  • Save bibek-magar/67e80f92ede677468f855adeed7f5d27 to your computer and use it in GitHub Desktop.
Save bibek-magar/67e80f92ede677468f855adeed7f5d27 to your computer and use it in GitHub Desktop.
Vanilla JS code to highlight the navigation.
/*
To check whether the given element in view port by visibility percentage
Tweak the number (20) as you need for the visibility percentage
*/
function isInViewport(element) {
const rect = element.getBoundingClientRect()
const viewportWidth =
window.innerWidth || document.documentElement.clientWidth
const viewportHeight =
window.innerHeight || document.documentElement.clientHeight
const visibleWidth =
Math.min(rect.right, viewportWidth) - Math.max(rect.left, 0)
const visibleHeight =
Math.min(rect.bottom, viewportHeight) - Math.max(rect.top, 0)
const visibleArea = visibleWidth * visibleHeight
const elementArea = element.offsetWidth * element.offsetHeight
const visibilityPercentage = (visibleArea / elementArea) * 100
return visibilityPercentage >= 20
}
// Adding classname to a tag if its is in viewport
function highlightNavLink() {
const sections = document.querySelectorAll('section')
const navLinks = document.querySelectorAll('.nav-link a')
// Remove "active" class from all navigation links
navLinks.forEach((link) => {
link.classList.remove('activeLink')
link.classList.add('inactiveLink')
})
// Add "active" class to the correct navigation link
sections.forEach((section) => {
const navLink = document.querySelector(`a[href="#${section.id}"]`)
if (navLink && isInViewport(section)) {
navLink.classList.add('activeLink')
}
})
}
// Usage
window.addEventListener('scroll', highlightNavLink)
// Optional you can add debounce as well to prevent continous calls upto 100ms to 200ms
function debounce(func, delay) {
let timeoutId
return function () {
const context = this
const args = arguments
clearTimeout(timeoutId)
timeoutId = setTimeout(() => {
func.apply(context, args)
}, delay)
}
}
// Debounce the scroll event to prevent continuous calls update the 100 as per your preference
const debouncedHighlightNavLink = debounce(highlightNavLink, 100)
// Usage for debounce
window.addEventListener('scroll', debouncedHighlightNavLink)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment