Smooth scroll anchor links WITHOUT jQuery

This is a pretty old question, but I think it's important to say that nowadays smooth scrolling is supported in CSS, so there's no need for any scripts:

html {
  scroll-behavior: smooth;
}

This property still has no support for Safari or IE/Edge as of 2019, so for a full crossbrowser support, you'll still have to use a script.


Using the function from here: JavaScript animation and modifying it to modify a property (not only a style's property), you can try something like this:

DEMO: http://jsfiddle.net/7TAa2/1/

Just saying...

function animate(elem, style, unit, from, to, time, prop) {
  if (!elem) {
    return;
  }
  var start = new Date().getTime(),
    timer = setInterval(function() {
      var step = Math.min(1, (new Date().getTime() - start) / time);
      if (prop) {
        elem[style] = (from + step * (to - from)) + unit;
      } else {
        elem.style[style] = (from + step * (to - from)) + unit;
      }
      if (step === 1) {
        clearInterval(timer);
      }
    }, 25);
  if (prop) {
    elem[style] = from + unit;
  } else {
    elem.style[style] = from + unit;
  }
}

window.onload = function() {
  var target = document.getElementById("div5");
  animate(document.scrollingElement || document.documentElement, "scrollTop", "", 0, target.offsetTop, 2000, true);
};
div {
  height: 50px;
}
<div id="div1">asdf1</div>
<div id="div2">asdf2</div>
<div id="div3">asdf3</div>
<div id="div4">asdf4</div>
<div id="div5">asdf5</div>
<div id="div6">asdf6</div>
<div id="div7">asdf7</div>
<div id="div8">asdf8</div>
<div id="div9">asdf9</div>
<div id="div10">asdf10</div>
<div id="div10">asdf11</div>
<div id="div10">asdf12</div>
<div id="div10">asdf13</div>
<div id="div10">asdf14</div>
<div id="div10">asdf15</div>
<div id="div10">asdf16</div>
<div id="div10">asdf17</div>
<div id="div10">asdf18</div>
<div id="div10">asdf19</div>
<div id="div10">asdf20</div>

Extending this answer: https://stackoverflow.com/a/8918062/3851798

After defining your function of scrollTo, you can pass the element you want to scrollTo in the function.

function scrollTo(element, to, duration) {
    if (duration <= 0) return;
    var difference = to - element.scrollTop;
    var perTick = difference / duration * 10;

    setTimeout(function() {
        element.scrollTop = element.scrollTop + perTick;
        if (element.scrollTop === to) return;
        scrollTo(element, to, duration - 10);
    }, 10);
}

If you have a div with an id="footer"

<div id="footer" class="categories">…</div>

In the script that you run to scroll you can run this,

elmnt = document.getElementById("footer");
scrollTo(document.body, elmnt.offsetTop, 600);

And there you have it. Smooth scrolling without jQuery. You can actually play around with that code on your browser's console and fine tune it to your liking.


Actually, there is more lightweight and simple way to do that: https://codepen.io/ugg0t/pen/mqBBBY

function scrollTo(element) {
  window.scroll({
    behavior: 'smooth',
    left: 0,
    top: element.offsetTop
  });
}

document.getElementById("button").addEventListener('click', () => {
  scrollTo(document.getElementById("8"));
});
div {
  width: 100%;
  height: 200px;
  background-color: black;
}

div:nth-child(odd) {
  background-color: white;
}

button {
  position: absolute;
  left: 10px;
  top: 10px;
}
<div id="1"></div>
<div id="2"></div>
<div id="3"></div>
<div id="4"></div>
<div id="5"></div>
<div id="6"></div>
<div id="7"></div>
<div id="8"></div>
<div id="9"></div>
<div id="10"></div>
<button id="button">Button</button>