I’m building a single-page portfolio and want to create a better user experience. Currently, when users click my navigation links, the page just "snaps" to the section ID, which feels very abrupt. I’ve seen sites where the page glides smoothly down to the target div. What is the standard jQuery script to capture a click on an anchor tag and animate the scrollTop position to that specific element's offset? Also, how do I handle the animation duration so it's not too fast?
3 answers
To achieve a smooth scroll, you need to use the .animate() method on the html and body elements. This ensures cross-browser compatibility, as some browsers track scroll position on the html tag and others on the body. You capture the click event, prevent the default "jump" behavior with e.preventDefault(), and then animate the scrollTop property to the target's .offset().top. The second parameter in the animate function is the duration in milliseconds; 800ms is usually the "sweet spot" for a natural feel. Using $(this.hash) is a clever way to directly select the target element based on the link's href.
That script works great for basic links, but what happens if I have a fixed header at the top of my page? Every time I scroll to a div, the top part of my content gets hidden behind the navigation bar. Is there a way to add an offset to the calculation so the scroll stops about 100 pixels above the actual div?
You can also use the native CSS property scroll-behavior: smooth; on your HTML tag. It’s a one-line fix that doesn't require jQuery at all for modern browsers.
I agree with Megan that CSS is easier, but I still use Kimberly's jQuery method for enterprise projects. The CSS version doesn't let you control the exact speed or add easing effects, and it can be inconsistent on older versions of Safari or IE.
Justin, you just need to subtract your header height from the offset value. Instead of just using target.offset().top, use target.offset().top - 100. This creates a "padding" at the top. Most developers now use a variable for this, like const headerHeight = $('.navbar').outerHeight();, to ensure that if the header size changes on mobile, the scroll offset stays accurate.