Scroll to Section
Scrolling scenarios
Specific pages, often the homepage hav sections that we want to directly scroll to in the global nav
All pages have
Solutions;
Must handle direct navigation e.g.
https://www.mysite.com/#contact
Must handle top-nav navigation from that page's nav bar
Ideally,
Should work perfectly on both staging and production, e.g. the origin does not need to be part of the URL
We do not want to have to handle in-page scrolling v. cross-page scrolling separately
CMS-link compatible
Keep the current state nav depending on the section you're on
Offset;
Support offsetting the scroll position for a fixed nav
Support sticky navs as well
Auto-calculate ( like Webflow does ) or allow a manual specification, stored on the body element
Options;
Hide the
#hash
Delay re-scroll, used for lazy-load
Just remove lazy-load ( bandwidth impacts )
Usage Notes
Avoid using the scroll-to-section option in links
Instead, form your links as relative links
Specific page
e.g. /#contact
e.g. /about/#contact
Current page
e.g. a section that you have on all pages, such as a Contact Us block that is part of your page footer.
e.g. #contact
Note the absence of the forward slash /
, which is the homepage path. Here we avoid adding a path that since we want to stay on the current page.
Link from another site
e.g. https://www.mysite.com/#contact
This will also work, and smooth-scroll
Technical Notes
function scrollToElementWithOffset() {
console.log('scrollToElementWithOffset triggered');
// Suppress the automatic hash scrolling behavior on page load
if (window.location.hash) {
// Temporarily remove the hash to prevent default jumping
const originalHash = window.location.hash;
history.replaceState(null, null, ' '); // Temporarily remove the hash
console.log('Suppressed initial hash:', originalHash);
setTimeout(() => {
// Check if there's a fixed-position element at the top of the body
const fixedElement = document.querySelector('body > *');
console.log('First element in body:', fixedElement);
let offset = 0;
if (fixedElement) {
const computedStyle = window.getComputedStyle(fixedElement);
console.log('Computed style of first element:', computedStyle.position);
if (computedStyle.position === 'fixed') {
offset = fixedElement.offsetHeight;
console.log('Fixed element detected with height:', offset);
} else {
console.log('First element is not fixed position');
}
} else {
console.log('No elements found in body');
}
// Restore the hash
history.replaceState(null, null, originalHash);
console.log('Restored the original hash:', originalHash);
// Now scroll to the target element with the correct offset
const element = document.querySelector(originalHash);
console.log('Target element for hash:', element);
if (element) {
// Calculate the target scroll position
const elementPosition = element.getBoundingClientRect().top + window.scrollY;
const offsetPosition = elementPosition - offset;
console.log('Element position:', elementPosition);
console.log('Offset position:', offsetPosition);
// Scroll to the position with the offset
window.scrollTo({
top: offsetPosition,
behavior: 'smooth'
});
console.log('Scrolling to position with offset');
} else {
console.log('No element found for the hash:', originalHash);
}
}, 0); // Run after the current event loop to ensure the DOM is ready
} else {
console.log('No hash in the URL');
}
}
// Run the function on page load and on hashchange
window.addEventListener('load', scrollToElementWithOffset);
window.addEventListener('hashchange', scrollToElementWithOffset);
Last updated
Was this helpful?