How to Create Smooth Scrolling When Clicking an Anchor Link

Smooth scrolling allows jumping between page sections in just one click without manually scrolling up or down. To have this feature on your page will definitely be appreciated by the users. So, let’s see what methods are used to create a smooth scrolling.

scrollIntoView()

The scrollIntoView() method is used for scrolling the view of the user to the element that it is called upon. Setting this value to “smooth” for the behaviour property will make the page scroll smoothly:

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the Document</title>
    <style>
      #element {
        height: 200px;
        width: 350px;
        overflow: auto;
      }
      #el1 {
        height: 200px;
        width: 1000px;
      }
      #el2 {
        height: 100px;
        width: 1000px;
      }
    </style>
  </head>
  <body>
    <div>
      <button onclick="scrollFunction1()"> Scroll to element-1 </button>
      <br>
      <button onclick="scrollFunction2()"> Scroll to element-2 </button>
      <br>
      <br>
      <br>
      <div id="element">
        <h2> 
          Click on the scroll button
        </h2>
        <div id="el1">
          <h2>Element-1</h2> </div>
        <div id="el2">
          <h2>Element-2</h2> </div>
      </div>
    </div>
    <script>
      function scrollFunction1() {
        let e = document.getElementById("el1");
        e.scrollIntoView({
          block: 'start',
          behavior: 'smooth',
          inline: 'start'
        });
      }
      function scrollFunction2() {
        let e = document.getElementById("el2");
        // This ends the block to the window 
        // bottom and also aligns the view to the center 
        e.scrollIntoView({
          block: 'end',
          behavior: 'smooth',
          inline: 'center'
        });
      }
    </script>
  </body>
</html>

scrollTop()

The scrollTop() jQuery method is used for scrolling to a particular section of the page. Animating this method will make the scroll smoother:

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the Document</title>
    <script src="https://code.jquery.com/jquery-3.5.0.min.js"></script>
    <style>
      #textDiv {
        height: 1500px;
      }
      p {
        margin-top: 100px;
        height: 500px;
      }
    </style>
  </head>
  <body>
    <div id='linkDiv'>
      <a href="#link1" class="scrollLink">Scroll to link1</a>
      <a href="#link2" class="scrollLink">Scroll to link2</a>
    </div>
    <div id="textDiv">
      <p id="link1"><strong>Anchor 1</strong> - Lorem ipsum dolor sit amet, nonumes voluptatum mel ea.</p>
      <p id="link2"><strong>Anchor 2</strong> - Ex ignota epicurei quo, his ex doctus delenit fabellas.</p>
    </div>
    <script>
      $(document).ready(function() {
          $("a.scrollLink").click(function(event) {
              event.preventDefault();
              $("html, body").animate({
                  scrollTop: $($(this).attr("href")).offset().top
                }, 500);
            });
        });
    </script>
  </body>
</html>

If the target element does not have an id, and you link to it by its name, you can use the following script:

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the Document</title>
    <script src="https://code.jquery.com/jquery-3.5.0.min.js"></script>
    <style>
      #textDiv {
        height: 1500px;
      }
      p {
        margin-top: 100px;
        height: 500px;
      }
    </style>
  </head>
  <body>
    <div id='linkDiv'>
      <a href="#link1" class="scrollLink">Scroll to link1</a>
      <a href="#link2" class="scrollLink">Scroll to link2</a>
    </div>
    <div id="textDiv">
      <p id="link1"><strong>Anchor 1</strong> - Lorem ipsum dolor sit amet, nonumes voluptatum mel ea.</p>
      <p id="link2"><strong>Anchor 2</strong> - Ex ignota epicurei quo, his ex doctus delenit fabellas.</p>
    </div>
    <script>
      $(document).ready(function() {
          $('a[href^="#"]').click(function() {
              $('html, body').animate({
                  scrollTop: $('[name="' + $.attr(this, 'href').substr(1) + '"]').offset().top
                }, 500);
              return false;
            });
        });
    </script>
  </body>
</html>

To increase the performance, you can cache the $('html, body') selector, so that it doesn't run every time the anchor link is clicked:

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the Document</title>
    <script src="https://code.jquery.com/jquery-3.5.0.min.js"></script>
    <style>
      #textDiv {
        height: 1500px;
      }
      p {
        margin-top: 100px;
        height: 500px;
      }
    </style>
  </head>
  <body>
    <div id='linkDiv'>
      <a href="#link1" class="scrollLink">Scroll to link1</a>
      <a href="#link2" class="scrollLink">Scroll to link2</a>
    </div>
    <div id="textDiv">
      <p id="link1"><strong>Anchor 1</strong> - Lorem ipsum dolor sit amet, nonumes voluptatum mel ea.</p>
      <p id="link2"><strong>Anchor 2</strong> - Ex ignota epicurei quo, his ex doctus delenit fabellas.</p>
    </div>
    <script>
      let $root = $('html, body');
      $(document).ready(function() {
          $(a.scrollLink).click(function() {
              $root.animate({
                scrollTop: $($.attr(this, 'href')).offset().top
              }, 500);
              return false;
            });
        });
    </script>
  </body>
</html>

To update the URL, do it within the animate callback:

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the Document</title>
    <script src="https://code.jquery.com/jquery-3.5.0.min.js"></script>
    <style>
      #textDiv {
        height: 1500px;
      }
      p {
        margin-top: 100px;
        height: 500px;
      }
    </style>
  </head>
  <body>
    <div id='linkDiv'>
      <a href="#link1" class="scrollLink">Scroll to link1</a>
      <a href="#link2" class="scrollLink">Scroll to link2</a>
    </div>
    <div id="textDiv">
      <p id="link1"><strong>Anchor 1</strong> - Lorem ipsum dolor sit amet, nonumes voluptatum mel ea.</p>
      <p id="link2"><strong>Anchor 2</strong> - Ex ignota epicurei quo, his ex doctus delenit fabellas.</p>
    </div>
    <script>
      let $root = $('html, body');
      $('a[href^="#"]').click(function() {
          let href = $.attr(this, 'href');
          $root.animate({
            scrollTop: $(href).offset().top
          }, 500, function() {
            window.location.hash = href;
          });
          return false;
        });
    </script>
  </body>
</html>

The hash property is used to set or return the anchor part of the href attribute value. The scrollTop() method is animated by enclosing it within the animate() method and defining the duration of the animation in milliseconds. The larger value, the slower the animation.

Do you find this helpful?

Related articles