Skip to content

Instantly share code, notes, and snippets.

@Dinamiko
Last active September 11, 2025 15:25
Show Gist options
  • Select an option

  • Save Dinamiko/c4546303da7094e35804b14872d25ebd to your computer and use it in GitHub Desktop.

Select an option

Save Dinamiko/c4546303da7094e35804b14872d25ebd to your computer and use it in GitHub Desktop.
Adds active style to menu items based on scroll position
<script>
/**
* Prevents wrong section position when accessing the page via URL hash, only runs once on page load.
* Handles URL hash anchors by triggering a click on the corresponding navigation item.
*/
(function () {
const validHashes = ['#top-nav', '#best-parks-regions', '#safaris', '#top-five-hotels', '#wildlife', '#best-time-to-visit'];
if (window.location.hash && validHashes.includes(window.location.hash)) {
const targetHash = window.location.hash;
document.addEventListener('DOMContentLoaded', function () {
// Find the link element with matching href
const targetLink = document.querySelector(`a[href="${targetHash}"]`);
if (!targetLink || !targetLink.id) {
//console.log(`No link found with href="${targetHash}" or link has no id`);
return;
}
const targetLinkId = targetLink.id;
//console.log(`Hash anchor detected: ${targetHash} - will trigger click when scrolling stops`);
let scrollTimeout;
let hasTriggered = false;
function onScrollStop() {
if (!hasTriggered) {
const linkById = document.getElementById(targetLinkId);
if (linkById) {
//console.log(`Scroll stopped - triggering click on menu item with id: ${targetLinkId}`);
linkById.click();
hasTriggered = true;
window.removeEventListener('scroll', handleScroll);
}
}
}
function handleScroll() {
clearTimeout(scrollTimeout);
scrollTimeout = setTimeout(onScrollStop, 50);
}
window.addEventListener('scroll', handleScroll);
});
}
})();
/**
* Dynamically highlights the active navigation item based on scroll position.
*/
document.addEventListener('DOMContentLoaded', function () {
const navConfig = [
{linkSelector: 'a[href="#top-nav"]', targetSelector: '#top-nav'},
{linkSelector: 'a[href="#best-parks-regions"]', targetSelector: '#best-parks-regions'},
{linkSelector: 'a[href="#safaris"]', targetSelector: '#safaris'},
{linkSelector: 'a[href="#top-five-hotels"]', targetSelector: '#top-five-hotels'},
{linkSelector: 'a[href="#wildlife"]', targetSelector: '#wildlife'},
{linkSelector: 'a[href="#best-time-to-visit"]', targetSelector: '#best-time-to-visit'}
];
const sections = [];
navConfig.forEach(config => {
const link = document.querySelector(config.linkSelector);
const target = document.querySelector(config.targetSelector);
if (link && target) {
sections.push({link, section: target});
}
});
function updateActiveNav() {
const scrollPos = window.scrollY + 100;
let activeSection = null;
sections.forEach(({section}) => {
const sectionTop = section.getBoundingClientRect().top + window.scrollY;
if (scrollPos >= sectionTop) {
activeSection = section;
}
});
sections.forEach(({link}) => {
link.style.color = '';
link.style.borderColor = '';
});
if (activeSection) {
const activeItem = sections.find(({section}) => section === activeSection);
if (activeItem) {
activeItem.link.style.color = '#c68546';
activeItem.link.style.borderColor = '#c68546';
}
}
}
window.addEventListener('scroll', updateActiveNav);
updateActiveNav();
});
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment