Preview:
  document.addEventListener("DOMContentLoaded", function () {
    const easeInOutQuad = function (t) {
      return t < 0.5 ? 2 * t * t
        : -1 + (4 - 2 * t) * t;
    };

    function smoothScrollTo(targetEl, duration = 500, offset = 80) {
      const startY = window.pageYOffset;
      const targetY = targetEl.getBoundingClientRect().top + startY - offset;
      const diff = targetY - startY;
      let startTime;

      function scrollStep(timestamp) {
        if (!startTime) startTime = timestamp;
        const time = timestamp - startTime;
        const percent = Math.min(time / duration, 1);
        window.scrollTo(0, startY + diff * easeInOutQuad(percent));
        if (time < duration) {
          window.requestAnimationFrame(scrollStep);
        }
      }

      window.requestAnimationFrame(scrollStep);
    }

    document.querySelectorAll('a[href^="#"]').forEach(link => {
      link.addEventListener("click", function (e) {
        const hash = this.getAttribute("href");
        const target = document.querySelector(hash);
        if (target) {
          e.preventDefault();
          smoothScrollTo(target, 5000, 80); // 500ms duration, 80px offset
        }
      });
    });
  });

downloadDownload PNG downloadDownload JPEG downloadDownload SVG

Tip: You can change the style, width & colours of the snippet with the inspect tool before clicking Download!

Click to optimize width for Twitter