JSFiddle - React, Tailwind, and code Playground

by brigand

HTML

<a href="#3">third</a>
<a href="#5">fifth</a>
<a href="#10">tenth</a>
<div>
  <h2>1<span class="target" id="1"></span></h2>
  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Soluta ducimus voluptatem obcaecati, nobis at, quasi nulla aut architecto repudiandae in laborum accusantium repellendus. Quasi recusandae sequi, facere illo sit doloribus.</p>
</div>
<div>
  <h2>2<span class="target" id="2"></span></h2>
  <p>Tenetur pariatur, molestias minus sit corrupti. Debitis obcaecati id dolorum fugit, voluptate illum harum corporis consequuntur assumenda optio mollitia dolore numquam eos dignissimos alias eveniet laborum tempora, eligendi earum explicabo.</p>
</div>
<div>
  <h2>3<span class="target" id="3"></span></h2>
  <p>Dolorem modi adipisci illo, pariatur deserunt praesentium mollitia blanditiis eaque dicta. Qui, eligendi! Accusamus eaque libero, eos consectetur sapiente deserunt in aut dolorum molestiae quisquam rem omnis illo blanditiis nobis.</p>
</div>
<div>
  <h2>4<span class="target" id="4"></span></h2>
  <p>Ad numquam molestiae, minima quia quod ratione placeat soluta, fuga tempore dolorem nam voluptas sed maxime, adipisci cupiditate magnam doloremque dignissimos totam. Repudiandae incidunt architecto quidem, natus labore expedita, sunt!</p>
</div>
<div>
  <h2>5<span class="target" id="5"></span></h2>
  <p>Architecto, debitis qui illum necessitatibus, id inventore pariatur, earum dolorem obcaecati eius voluptas vero aliquam quasi rem mollitia neque. Ipsa incidunt, exercitationem, aliquid explicabo repellendus doloribus dignissimos ratione voluptate nulla.</p>
</div>
<div>
  <h2>6<span class="target" id="6"></span></h2>
  <p>Molestias provident illum aliquid vel, mollitia quas dolore sapiente blanditiis illo excepturi eum facilis magni nisi quos dolorum sit, laboriosam labore esse vitae, distinctio omnis eveniet, deleniti! Sit, sint, error?</p>
</div>
<div>
  <h2>7<span class="target" id="7"></span></h2>
  <p>Id quam dolorum mollitia, assumenda...

CSS

h2 {
  position: relative;
}

.target:target {
  width: 100%;
  height: 3px;
  background: hotpink;
}

JavaScript

const TOP_PADDING = 100;

let lastHash = null;
let time = null;
let hashDirty = false;

window.addEventListener('hashchange', () => {
  if (time && time > Date.now() - 100) {
    update();
    time = Date.now();
    hashDirty = false;
  } else {
    hashDirty = true;
  }
})

window.addEventListener('scroll', () => {
  if (hashDirty) {
    update();
  } else {
    time = Date.now();
  }
});

function update() {
  const id = document.location.hash.replace('#', '');
  if (!id) {
    return;
  }
  const target = document.getElementById(id);

  const y = target.getBoundingClientRect().top + window.scrollTop;

  window.scrollTo(0, y - TOP_PADDING);
}