-
-
Notifications
You must be signed in to change notification settings - Fork 2k
feat(#1932): implement smooth scrolling for anchor navigation across site #1965
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(#1932): implement smooth scrolling for anchor navigation across site #1965
Conversation
✅ Deploy Preview for expressjscom-preview ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
js/app.js
Outdated
| $(document).on('click', 'a[href^="#"]:not([href="#"]):not([href="#top"])', function(e) { | ||
| var href = $(this).attr('href'); | ||
| if (smoothScrollToElement(href)) { | ||
| e.preventDefault(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you please remove this line https://github.com/expressjs/expressjs.com/blob/gh-pages/js/menu.js#L186 ? Since default behavior stopped here.
js/app.js
Outdated
| }); | ||
|
|
||
| // Smooth scrolling for all anchor links | ||
| $(document).on('click', 'a[href^="#"]:not([href="#"]):not([href="#top"])', function(e) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| $(document).on('click', 'a[href^="#"]:not([href="#"]):not([href="#top"])', function(e) { | |
| $("#api-doc").on('click', 'a[href^="#"]:not([href="#"]):not([href="#top"])', function(e) { |
We should minimize the scope of this click event. Currently, $(document).on('click'...) attaches the handler to all anchor links with # across every page. However, smooth scrolling is only needed on API pages, since the TOC exists only there. Scoping it to #api-doc avoids unnecessary event handling and prevents inconsistent anchor # behavior on other pages. Also, checking "#api-doc" exist on page is required before applying click event.
bjohansebas
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the PR!
As i mentioned in the issue, this can be handled through CSS, javascript is not necessary.
I am OK with CSS only solution. But this approach comes with some limitations, like we cannot control scroll behavior and can not add header offsets. But it is fine if headings are not hiding behind the header bar on anchor link click. |
|
Thanks @bjohansebas for the suggestion about a CSS-only solution!
So I’d propose keeping the JS smooth scroll, scoped only to Let me know if you’d prefer another approach! |
The headings are never hidden by the header bar, or at least I’ve been trying to reproduce it and haven’t been able to.
That doesn’t matter in CSS, since the effect will be applied to all elements anyway. * {
scroll-behavior: smooth;
} |
|
Hi @bjohansebas and @ShubhamOulkar, I’ve updated the implementation to follow your suggestion of a CSS-only smooth scrolling solution.
Let me know if you’d like any further changes! |
| h1, h2, h3, h4, h5, h6, | ||
| [id] { | ||
| scroll-margin-top: 120px; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if this is actually doing anything, and if it's supposed to have the same effect as in the MDN example https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-margin-top, then I'm -1 on this, I don't think we should do it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| without scroll top margin | with scroll top margin |
|---|---|
![]() |
![]() |
We can clearly see that margin spaces added to the header on scroll from the top of the viewport.
This property is used to increase visible area around the target element so that it is accessible to the user.
In our context, why it is important?
I expressed my concerns over the issue of hiding headers behind the top navigation bar in a comment above.
But it is fine if headings are not hiding behind the header bar on anchor link click.
This happens if top navigation is positioned sticky at the top. See image, express.raw() hide behind sticky top navigation.

It is not required right now, without scroll top margin, header scroll into viewport at top 0px. But I think adding some small margin 60px to the top looks good for me. Also our header is 57px height. Maybe I will go with sticky top navigation bar in #1943.

css/style.css
Outdated
| /* handle header offset with scroll-margin */ | ||
| h1, h2, h3, h4, h5, h6, | ||
| [id] { | ||
| scroll-margin-top: 120px; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| scroll-margin-top: 120px; | |
| scroll-margin-top: 60px; |
see comment https://github.com/expressjs/expressjs.com/pull/1965/files#r2206464995
| padding-top: 40px; | ||
| } | ||
|
|
||
| #api-doc *:target, #page-doc *:target { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I support removing this
since we are using scroll top margin only on headers.
ShubhamOulkar
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please do remove this line https://github.com/expressjs/expressjs.com/blob/gh-pages/js/menu.js#L186. On TOC main section heading click, it should scroll to main sections on the page. Currently, it is disabled. Only subsections get scrolled.
…reventDefault for TOC links
|
Hi @bjohansebas and @ShubhamOulkar, Thanks so much for the thoughtful reviews! Regarding
I’ll adjust the value to 60px as suggested, since our header height is ~57px. Remove Let me know if there’s anything else you’d like tweaked! |
ShubhamOulkar
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just tested, but default CSS scroll is too fast. On clicking main menu, the page scrolls really fast to that menu. Should we try putting some animation key frames to add some delays to scrolls?
|
hi @ShubhamOulkar, Thank you for the suggestion regarding adding delays to scroll using animation keyframes. I explored the possibility of controlling scroll speed using CSS keyframes alone. However, after testing locally, it turns out that CSS keyframes cannot manipulate scroll behavior that we need. While To achieve the effect you’re suggesting (slower or delayed scrolling), we would need to implement a small JavaScript solution that programmatically controls the scroll animation. Please let me know if you'd like me to proceed with a JavaScript-based implementation to match the desired behavior, or if you have any other suggestions — I’d be grateful to explore them! Thanks! |
I’m -1 on implementing this in JavaScript. I want to simplify things as much as possible, and I don’t see it as reasonable to maintain that JavaScript when the platform itself already provides this solution (it might not be perfect, but it’s better than having to maintain JavaScript). |
…r submenu links Signed-off-by: Sebastian Beltran <[email protected]>
🚦 Lighthouse Results (Mobile & Desktop)
|
🚦 Lighthouse Results (Mobile & Desktop)
|
bjohansebas
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
ShubhamOulkar
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need to remove line no 5 from app.js. Otherwise LGTM 👍


Description
This PR implements smooth scrolling for in-page navigation across the Express.js website as mentioned in Issue : #1932
This improves the user experience by ensuring that navigation to sections via anchor links transitions smoothly, rather than jumping abruptly.
Closes #1932
Video
smooth-scrolling.mp4