In this new tutorial, we’ll learn how to implement smooth scrolling in our web pages. We’ll start with a pure CSS solution and then move on to a common jQuery approach for creating this functionality. Next, we’ll get rid of jQuery and discuss two pure JavaScript solutions.
Just to give you an idea of what we’ll discuss during this tutorial, check out one of the demos we’ll be building:
Let’s get started!
1. Begin With the HTML Markup
For demonstration purposes, we’ll define a header wrapped within a container and four sections. Inside it, we’ll specify a navigation menu and an introductory text.
Each section will have an id
whose value will match the href
value of a menu link. This association (what we refer to as a fragment identifier) will allow us to jump to specific parts of our page.
Here’s the HTML:
<div class="container"> ... <header class="page-header"> <nav> <ul> <li> <a href="#...">...</a> </li> <!-- more links --> </ul> </nav> <div class="header-text">...</div> </header> </div> <section class="section" id="">...</section> <section class="section" id="">...</section> <section class="section" id="">...</section> <section class="section" id="">...</section>
2. Define the Styles
The CSS part will be pretty straightforward, nothing extraordinary.
First, we’ll use CSS Grid to layout the page header. The menu will cover one-fourth of the available width, while the text the remaining three-fourths (the responsive stuff isn’t really important here):
.page-header { display: grid; grid-column-gap: 30px; grid-template-columns: 1fr 3fr; padding: 40px 0; border-top: 1px solid; border-bottom: 1px solid; margin-bottom: 150px; } .header-text { font-weight: bold; }
Coming up next, we’ll apply some styles to the sections. Most importantly, we’ll ensure that they will be tall enough, so there’s adequate scrolling inside the page for the effect:
/*CUSTOM VARIABLES HERE*/ .section { padding: 150px 0; } .section:nth-of-type(1), .section:nth-of-type(3) { background: var(--beige); } .section-text { margin: 50px 0; max-width: 800px; } .section-btn { display: inline-block; color: var(--beige); background: var(--black); min-width: 200px; height: 50px; padding: 9px 40px; text-align: center; }
That’s all we need so far! If we now click on a specific link, we’ll immediately jump to the relevant page section.
Check out our initial demo:
Basic HTML stuff, right? Let’s now take it a step further and learn how to navigate to the sections smoothly.
3. Smooth Scrolling With CSS
The easiest and quickest approach for applying smooth scrolling inside a page is via the following rule:
html { scroll-behavior: smooth; }
Let's explain.
There's a relatively new CSS property called scroll-behavior
. This property accepts two values: auto
(default) and smooth
. As soon as we give scroll-behavior: smooth
to the html
element, the magic will happen, and we’ll be able to navigate to the target section smoothly.
Note: if you set scroll-behavior: smooth
to the body
element, smooth scrolling won't work.
As an additional note, keep in mind that at the time of this writing, there isn’t any speed
option defined in the specification for manipulating the animation speed.
Here's the associated demo:
Solution Review
Although it's a great and promising CSS feature, it still lacks wide support. For example, at the time of this writing, no Safari version supports it.
4. Smooth Scrolling With jQuery
We'll continue with the traditional jQuery approach. That said, to create smooth scrolling with jQuery, we’ll take advantage of its animate()
method.
Each time we click on a navigation link, we’ll do the following things:
- Cancel its default behavior to jump to the corresponding section.
- Grab its
href
attribute value. - Smoothly navigate to the associated section by animating the
scrollTop
property. Note that theanimate()
method allows us to adjust the animation speed. In our case, the animation will last 800ms.
Here’s the jQuery code:
$(".page-header ul a").on("click", function (e) { // 1 e.preventDefault(); // 2 const href = $(this).attr("href"); // 3 $("html, body").animate({ scrollTop: $(href).offset().top }, 800); });
And the related demo:
Solution Review
The major downside of this method is that you have to load an extra JavaScript library. On the contrary, it's a reliable solution that will work well on different screens/devices and you can customize the scrolling speed. My recommendation is to use it only if your project already uses or needs jQuery.
5. Smooth Scrolling With Vanilla JavaScript
At this point, we’ll throw away jQuery and concentrate on two pure JavaScript solutions. Happily enough, it’s much simpler than you might expect.
Using the scroll()
Method
First, we’ll use the scroll()
method. The logic for this approach is similar to the previous jQuery implementation.
Inside this method, we’ll determine the scrolling behavior via the behavior
configuration property. This property is the JavaScript representation of the scroll-behavior
CSS property and can receive the auto
(default) and smooth
values. Again here, all we have to do is to set the value of the behavior
property to smooth
.
Here’s the required code:
const links = document.querySelectorAll(".page-header ul a"); for (const link of links) { link.addEventListener("click", clickHandler); } function clickHandler(e) { e.preventDefault(); const href = this.getAttribute("href"); const offsetTop = document.querySelector(href).offsetTop; scroll({ top: offsetTop, behavior: "smooth" }); }
Tip: instead of the scroll()
method, we could equally have used the scrollTo()
and scrollBy()
methods. The effect should look the same.
Here’s the associated demo:
Using the scrollIntoView()
Method
Beyond the aforementioned scroll methods which are attached to the window
object (i.e. window.scroll()
), there’s also the scrollIntoView()
method which applies to DOM elements. This can accept as well the familiar behavior
property with the value set to smooth
.
Here’s the code needed for this implementation:
const links = document.querySelectorAll(".page-header ul a"); for (const link of links) { link.addEventListener("click", clickHandler); } function clickHandler(e) { e.preventDefault(); const href = this.getAttribute("href"); document.querySelector(href).scrollIntoView({ behavior: "smooth" }); }
The related demo:
Solutions Review
The native JavaScript version of smooth scrolling requires more code compared to the native CSS property. Like the CSS solution, it still lacks extended support, and there's no easy way to control the scrolling speed unless we write our code.
6. Polyfills Please?
As already discussed, native smooth scrolling with CSS or JavaScript is still somehow limited.
However, there are polyfills out there in case you need them. For instance, there's the Smooth Scroll polyfill with over 3.4k GitHub stars developed by Dustan Kasten.
To include it in your projects, grab it from a CDN, then insert it as a script
tag before your JavaScript code.
In our case, as soon as we load it in one of our JavaScript demos, the scrolling animation will work in browsers like Safari and devices like iPad Mini 4. But, if we add it in our CSS demo, the scrolling animation won't work on unsupported browsers/devices.
Here’s one of our aforementioned JavaScript demos with the polyfill embedded:
Conclusion
That’s it, folks! Today we covered some options for achieving smooth scrolling with CSS and JavaScript (including jQuery).
I hope you found this exercise useful and have enhanced your front-end knowledge a little bit. If you have ever built something similar in the past, please share it with us via social media.
Challenge: before closing, I have a small challenge for you! Your job is to extend one of our JavaScript demos by including a “back to top” button. The final functionality should work like this demo. Do you accept the challenge? If so, I’d be glad to see your solution!
As always, thanks a lot for reading!
No comments:
Post a Comment