103

I can scroll to 200px using the following

btn.addEventListener("click", function(){
    window.scrollTo(0,200);
})

But I want a smooth scroll effect. How do I do this?

kind user
  • 40,029
  • 7
  • 67
  • 77
KolaCaine
  • 2,037
  • 5
  • 19
  • 31
  • 3
    Possible duplicate of [Smooth scrolling when clicking an anchor link](http://stackoverflow.com/questions/7717527/smooth-scrolling-when-clicking-an-anchor-link) – Faegy Feb 15 '17 at 23:21
  • 2
    Just a note for future generations (available from Chrome 61) "The CSSOM View Smooth Scroll API brings native smooth scrolling to the platform through a the scroll-behavior: smooth CSS property or by using the window.scrollTo() DOM scroll method, eliminating the need to implement this behavior with JavaScript" – Dominic Aug 18 '17 at 07:47
  • Place an empty element in the top of your page, then you can use document.querySelector('your-element').scrollIntoView({behavior: 'smooth'}); – Antonio Brandao Jan 31 '18 at 19:29
  • 6
    It is possible to do using. `window.scrollTo({ top: 200, behavior: 'smooth' });` I'd like to add it as anwer but question is closed. – karoluS Aug 01 '18 at 07:23
  • 3
    DOH! US English - behaviour: 'smooth' will get you nowhere... – A2D Sep 19 '18 at 00:55

2 Answers2

258

2023 Update

Now you can use just window.scrollTo({ top: 0, behavior: 'smooth' }) to get the page scrolled with a smooth effect.

const btn = document.getElementById('elem');

btn.addEventListener('click', () => window.scrollTo({
  top: 400,
  behavior: 'smooth',
}));
#x {
  height: 1000px;
  background: lightblue;
}
<div id='x'>
  <button id='elem'>Click to scroll</button>
</div>

Older solutions

You can do something like this:

var btn = document.getElementById('x');

btn.addEventListener("click", function() {
  var i = 10;
  var int = setInterval(function() {
    window.scrollTo(0, i);
    i += 10;
    if (i >= 200) clearInterval(int);
  }, 20);
})
body {
  background: #3a2613;
  height: 600px;
}
<button id='x'>click</button>

ES6 recursive approach:

const btn = document.getElementById('elem');

const smoothScroll = (h) => {
  let i = h || 0;
  if (i < 200) {
    setTimeout(() => {
      window.scrollTo(0, i);
      smoothScroll(i + 10);
    }, 10);
  }
}

btn.addEventListener('click', () => smoothScroll());
body {
  background: #9a6432;
  height: 600px;
}
<button id='elem'>click</button>
kind user
  • 40,029
  • 7
  • 67
  • 77
  • That right ! Thanks so much – KolaCaine Feb 15 '17 at 23:36
  • Is this an efficient method? – darkace Nov 30 '17 at 16:39
  • 1
    For really smooth transitions you rather use `requestAnimationFrame` https://codepen.io/dsheiko/pen/XZEgXW – Dmitry Sheiko Feb 20 '18 at 12:11
  • 6
    1year after, I think the `scrollTo`are evolved, your script are deprecated for me because now, we can pass an object into `scrollTo` like that : `window.scrollTo({ top: 0, behavior: 'smooth' });` And we are the same effect with less line code, and it's supported by old and recent browser :) – KolaCaine Aug 10 '18 at 09:44
  • 2
    @KolaCaine Thanks, I've updated my answer :) – kind user Aug 17 '18 at 15:58
  • Seems to be a bug in Edge at the moment preventing ScrollTo from working: https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/15534521/ – Ian Sep 20 '18 at 19:16
  • 5
    Safari for OSX seems to ignore the `behavior: 'smooth'` parameter while using `window.scrollTo`. – Petr Nagy Oct 22 '18 at 12:09
  • 7
    @PetrNagy yea `behavior: 'smooth'` also not working on iOS. I think we still need to use the old solution for WebKit on Mac and iOS. – Jonny Jan 28 '19 at 15:33
  • Is there a way to stop the scrolling before it reaches it's end position? For example, you have a button click to initiate the scroll with a top position of 400. What about another button with a click event to stop the scroll wherever it currently is at it's current point in time? Say while it's scrolling and it's reached 250, you hit the button and it would stop the scroll at 250 instead of the initial 400 you currently set as the top param for the first button? – Andrew Jul 26 '19 at 19:02
  • @Andrew You mean the solution with recursion? Not the `behavior` method? – kind user Aug 18 '19 at 23:39
  • in windows (win 10 edu v1909), css `scroll-behavior: smooth` is not smooth if you disable `display animations in windows` in control panel. So you have to choose @kinduser 's **old solution** if you want your smooth scrolling happens in any case – Simon Dehaut May 05 '20 at 19:35
  • **but is there any way to set the rate at which it scrolls?** it seems always at some point when you increase the amount of scroll that it becomes "jumpy" instead of smooth :/ – oldboy Nov 10 '20 at 07:32
  • behavior: 'smooth' has never worked for me in any browser. Does this work for anyone? – Seven Systems Jul 21 '21 at 11:24
  • If you use `getElementsByClassName` instead `getElementById`, will occur the error: `".addEventListener is not a function"`, to solve it use `btn[0].addEventListener`. See more in [link](https://stackoverflow.com/questions/32027935/addeventlistener-is-not-a-function-why-does-this-error-occur) – Leffa Apr 29 '22 at 14:47
  • to behavior works, use in the CSS `html:focus-within { scroll-behavior: smooth;}` – Leffa Apr 29 '22 at 14:50
  • `window.scrollTo({ top: 0, behavior: 'smooth' })` seems to be working for me on Safari in Jun 2022, macOS Monterey, Safari 15.4 – yiwei Jun 15 '22 at 20:50
4
$('html, body').animate({scrollTop:1200},'50');

You can do this!

Justin Liu
  • 581
  • 6
  • 21
Myco Claro
  • 475
  • 2
  • 14
  • 3
    Yes, I'm right with you, but you are using jQuery, and I want using only Vanilla. But I agree with you, with jQuery is more simple – KolaCaine Feb 16 '17 at 02:29
  • yes bro. that's only jquery but you can use that. jQuery is very simple. – Myco Claro Feb 16 '17 at 02:31
  • 39
    Is the problem, jQuery is simple.. And I don't like when is simple. I prefer to go deeper my knowledge in pure JS (Vanilla) and after that I can use jQuery. It's my philosophy – KolaCaine Feb 16 '17 at 02:34
  • Not only that but jquery can cause some serious jank when scrolling while changing the height of elements (using `.show()` or `.slideDown()` while using `scrollTop()` for instance). jQuery can be nice for quick/trivial stuff, but it's just a facade for real js. Check this one out! https://pawelgrzybek.com/page-scroll-in-vanilla-javascript/ – admcfajn Mar 03 '18 at 00:10
  • 6
    1year after, I think the `scrollTo`are evolved, your script are deprecated for me because now, we can pass an object into `scrollTo` like that : `window.scrollTo({ top: 0, behavior: 'smooth' });` And we are the same effect with less line code, and it's supported by old and recent browser :) – KolaCaine Aug 10 '18 at 09:45