4

I am new to js.

I need a scrolling a page based on the <a> tag href attribute in my college project.

The ScrollTop functionality is not working as my project was a single page application. I can achive that using the functionality by window.scrollTo(x-coord, y-coord);.

But now the problem is I want to make a smooth scroll effect in my page.

How do I achieve it in the scrollTo(x,y) function???

Thanks in advance. :)

Ashish Bahl
  • 1,482
  • 1
  • 18
  • 27
Parthasarathy
  • 308
  • 2
  • 10

2 Answers2

2

Distance & Speed

If you want to control the distance to scroll AND the speed, you can use the below function:

/**
 * A function to scroll a given amount of y pixels in a given time
 */
async function scrollByY(y, time) {
  const start = performance.now()
  const startY = window.scrollY
  const endY = startY + y
  while (performance.now() < start + time) {
    const progress = (performance.now() - start) / time
    window.scrollTo(0, startY + y * progress)
    // wait for the next frame
    await new Promise(requestAnimationFrame)
  }
  window.scrollTo(0, endY)
}

document.querySelector("#one").addEventListener("click", async () => {
  await scrollByY(100, 500)
})

document.querySelector("#two").addEventListener("click", async () => {
  await scrollByY(200, 2000)
})
<body style="margin: 0">
  <div style="position: fixed">
    <button id="one">scroll 100px in 0.5s</button>
    <button id="two">scroll 200px in 2s</button>
  </div>
  <div style="background: yellowgreen; height: 100px"></div>
  <div style="background: orange; height: 100px"></div>
  <div style="background: darkgoldenrod; height: 100px"></div>
  <div style="background: darkolivegreen; height: 100px"></div>
  <div style="background: blueviolet; height: 100vh"></div>
</body>
David Wolf
  • 1,400
  • 1
  • 9
  • 18
1

In 2018, you can now implement Smooth Scrolling natively (ie. in vanilla javascript), using the new API for:

  • Element.scrollTo({ScrollingOptionsObject})
  • Element.scrollBy({ScrollingOptionsObject})
  • Element.scrollIntoView({ScrollingOptionsObject})

Browser Support Here:


Working example of Vanilla Javascript Smooth Scrolling:

var pageLinks = [... document.querySelectorAll('li button')];

function scrollToSection(e) {

    var targetSection = document.getElementById(e.target.dataset.targetSection);
    targetSection.scrollIntoView({behavior: 'smooth'});
}

for (let i = 0; i < pageLinks.length; i++) {

    pageLinks[i].addEventListener('click', scrollToSection, false);
}
ul {
margin-bottom: 480px;
}

button {
color: rgb(0,0, 239);
text-decoration: underline;
background: none;
border: none;
cursor: pointer;
}

section {
display: block;
width: 50%;
height: 300px;
margin: 12px 0 96px;
padding: 6px;
border: 1px solid rgb(127, 127, 127);
}
<ul>
<li><button type="button" data-target-section="section-1">Go to Section 1</button></li>
<li><button type="button" data-target-section="section-2">Go to Section 2</button></li>
<li><button type="button" data-target-section="section-3">Go to Section 3</button></li>
<li><button type="button" data-target-section="section-4">Go to Section 4</button></li>
<li><button type="button" data-target-section="section-5">Go to Section 5</button></li>
</ul>

<section id="section-1" class="section-1">
<h2>This is Section 1</h2>
</section>

<section id="section-2" class="section-2">
<h2>This is Section 2</h2>
</section>

<section id="section-3" class="section-3">
<h2>This is Section 3</h2>
</section>

<section id="section-4" class="section-4">
<h2>This is Section 4</h2>
</section>

<section id="section-5" class="section-5">
<h2>This is Section 5</h2>
</section>

Further Reading about the new Javascript Smooth Scrolling API:


And if you liked that... here's something really exciting:

The browser support for the CSS value scroll-behaviour is slightly behind the browser support for the javascript API above - but where it is implemented it can do something amazing, like this:

body {scroll-behavior: smooth;}

Browser Support Here:


Working example of CSS Smooth Scrolling:

:root {
scroll-behavior: smooth;
}

ul {
margin-bottom: 480px;
}

section {
display: block;
width: 50%;
height: 300px;
margin: 12px 0 96px;
padding: 6px;
border: 1px solid rgb(127, 127, 127);
}
<ul>
<li><a href="#section-1">Go to Section 1</a></li>
<li><a href="#section-2">Go to Section 2</a></li>
<li><a href="#section-3">Go to Section 3</a></li>
<li><a href="#section-4">Go to Section 4</a></li>
<li><a href="#section-5">Go to Section 5</a></li>
</ul>

<section id="section-1" class="section-1">
<h2>This is Section 1</h2>
</section>

<section id="section-2" class="section-2">
<h2>This is Section 2</h2>
</section>

<section id="section-3" class="section-3">
<h2>This is Section 3</h2>
</section>

<section id="section-4" class="section-4">
<h2>This is Section 4</h2>
</section>

<section id="section-5" class="section-5">
<h2>This is Section 5</h2>
</section>
Rounin
  • 27,134
  • 9
  • 83
  • 108
  • 1
    hey @Rounin, how are you? I am looking for a solution smoother than ```{...behaviour: "smooth"}``` Any way to really control how many ```ms``` this scrolling animation takes to finish? – Arp Oct 12 '20 at 02:19
  • It's probably best to ask this as your own new question, @Alioshr. – Rounin Oct 12 '20 at 08:58
  • Note: `.scrollIntoView()` is finicky in Chrome. See: https://github.com/iamdustan/smoothscroll/issues/28 (This is an issue on a smooth scroll polyfill, but they talk about the Chrome's behavior and fixes for it.) – Ouroborus Mar 31 '21 at 22:58