当我们在阅读页面文档的时候,如果这个文档特别长,分成多级标题,这时候我们会有快速定位的需求。这时候,我们就可以利用 anchor locating 来快速实现。这是浏览器的默认行为,定位之后便会跑到页面的最顶部。
capture1.gif
简单代码如下:

  1. <aside>
  2. <ul>
  3. <li>
  4. <a href="#react">React</a>
  5. </li>
  6. <li>
  7. <a href="#remix">Remix</a>
  8. </li>
  9. <li>
  10. <a href="#next">Next</a>
  11. </li>
  12. <li>
  13. <a href="#svelte">Svelte</a>
  14. </li>
  15. </ul>
  16. </aside>
  17. <article>
  18. <h2 id="react">
  19. <a href="#react" class="header-anchor">#</a>
  20. React
  21. </h2>
  22. <p>Lorem ipsum dolor sit, <strong>amet consectetur adipisicing elit</strong>. Ducimus, aut animi. Labore sit
  23. mollitia numquam magni ipsam ex iusto maxime fuga nostrum adipisci vel alias soluta est tempore eos quos
  24. dolorem, corrupti quisquam ab. Velit dicta quidem, quasi eum natus incidunt numquam id amet iure in voluptate
  25. eligendi ipsa ducimus consectetur error aliquid deleniti odio provident tempore similique. Ipsa, eum
  26. dignissimos! Nam facere quae eum atque dolore dolores, distinctio vel, doloremque molestiae, iure accusantium
  27. minus itaque voluptatem quo. Aspernatur officiis vitae eveniet ab ducimus eos sapiente porro? Laboriosam ipsam,
  28. distinctio beatae reprehenderit itaque dicta reiciendis temporibus quod. Quasi, blanditiis! In.</p>
  29. <h2 id="remix">
  30. <a href="#remix" class="header-anchor">#</a>
  31. React
  32. </h2>
  33. <p>Lorem ipsum dolor sit, <strong>amet consectetur adipisicing elit</strong>. Ducimus, aut animi. Labore sit
  34. mollitia numquam magni ipsam ex iusto maxime fuga nostrum adipisci vel alias soluta est tempore eos quos
  35. dolorem, corrupti quisquam ab. Velit dicta quidem, quasi eum natus incidunt numquam id amet iure in voluptate
  36. eligendi ipsa ducimus consectetur error aliquid deleniti odio provident tempore similique. Ipsa, eum
  37. dignissimos! Nam facere quae eum atque dolore dolores, distinctio vel, doloremque molestiae, iure accusantium
  38. minus itaque voluptatem quo. Aspernatur officiis vitae eveniet ab ducimus eos sapiente porro? Laboriosam ipsam,
  39. distinct</p>
  40. </article>

这样我们就利用了浏览器的默认行为,实现了最基本的定位操作。
如果我们再进一步,当前页面如果有 header 的情况下,再使用这种行为就会出现差错。
capture2.gif
这是因为,此时页面仍然会使用默认的行为,继续定位到页面的最顶端,而如果我们想要定位到 header 的下方某个位置,我们就需要做一些额外的操作。

设置margin增加高度

默认的定位位置是当前 anchor 所占据的高度,包括所设置的 padding-top值。
image.png
这时候我们可以模拟一个额外的高度来达到想要的效果。

  1. <h2 id="react">
  2. <a href="#react" class="header-anchor">#</a>
  3. React
  4. </h2>
  1. .header-anchor {
  2. font-size: 0;
  3. display: block;
  4. height: 100px;
  5. margin-top: -100px;
  6. visibility: hidden;
  7. }

我们为 a 标签设置了一个特定的高度,然后在设置一个负值的 margin-top来让其归位,使用这种方法,我们便可以达到设置偏移量的效果。
capture3.gif

设置scroll-margin-top属性

还有一个更简便的方法,我们可以给对应的标签设置 scroll-margin-top即可达到对应的效果。

  1. <h2 id="react">
  2. <a href="#react" class="header-anchor">#</a>
  3. React
  4. </h2>
  1. h2 {
  2. scroll-margin-top: 100px;
  3. }

这是一种更为简便的方法来实现偏移的效果。对应的兼容性也是比较好的。
image.png

使用 JS 接管默认行为

我们还可以使用 JS 来监听 hashchange事件,阻止默认行为 e.preventDefault()并使用 window.scrollTo() 来计算出特定的滚动位置。

  1. const targetTop =
  2. window.scrllY + target.getBoundingClientRect().top - offset + targetPadding

这里的 offset就是我们需要手动设置的偏移量。
image.png
获取完特定的偏移量之后,我们就可以使用window.scrollTo:

  1. window.scrollTo({
  2. top: targetTop,
  3. behavior: 'smooth'
  4. })

capture3.gif