为所有哈希链接/调用的滚动位置添加自动偏移量

Adding an automatic offset to the scroll position for all hash-links/calls

本文关键字:位置 滚动 添加 偏移量 调用 哈希 链接      更新时间:2023-09-26

我有以下问题:

就像在Facebook上一样,我在页面顶部有一个始终可见的菜单栏(position: fixed;)。当我现在单击页面上的哈希链接(或加载 url 中带有哈希的新页面)跳转到页面上的某个元素时,浏览器总是将此元素滚动到页面的最顶部,这意味着该元素位于顶部菜单栏后面。

我想添加一些Javascript(jQuery或普通Javascript),它会自动向此滚动位置添加(负)偏移量,以便在单击链接或加载页面时,链接元素位于顶部菜单栏的正下方。但我不只是想将事件侦听器添加到所有处理此问题的链接中。我还想要一个有效的解决方案,如果页面使用浏览器的地址栏在 url 中加载哈希部分(或者当链接到 url 末尾带有哈希的其他页面时)。

你能帮我这个吗?提前感谢!:)

实际上,我自己找到了一个仅适用于我的解决方案,仅使用 css:

我向跳转链接指向的元素添加了一个margin-top: -40px;padding-top: 40px;。这适用于所有主流浏览器:IE(7-9),Firefox,Opera,Chrome和Safari。

唯一的问题:如果此元素位于浮动元素之后,则负边距不起作用(意味着正填充变得可见)。如果有人知道解决方案/解决方法,请发表评论。然后我会更新我的帖子。谢谢!

> 如今,在 2021 年,有一个很好的简单 only-css 解决方案,具有:targetscroll-margin-top

:target {
    scroll-margin-top: 100px;
}

它适用于所有主流浏览器

引用:

  • https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-margin-top
  • https://developer.mozilla.org/en-US/docs/Web/CSS/%3Atarget

我发现这种在 css 中添加:before的方法似乎效果很好。

h2:before { 
  display: block; 
  content: " "; 
  margin-top: -285px; 
  height: 285px; 
  visibility: hidden; 
}

更多关于CSS Tricks网站

为了补充解决方案,我发现将显示设置为 none 解决了在浮动元素中使用时填充可见的问题。

所以:

.symbol-target {
    padding-top: 40px;
    margin-top: -40px;
    width: 1px; /* '0' will not work for Opera */
    display: none;
}

我还将此样式作为目标内容上方的空div 包含在内。

举个例子,考虑D的bootDoc解决方案,它适用于所有主流浏览器:

CSS(插入标题栏高度而不是40px):

.symbol-target {
    padding-top: 40px;
    margin-top: -40px;
    width: 1px; /* '0' will not work for Opera */
    display: inline-block;
}

.HTML:

<h3>
    <span class="symbol-target" id="myTarget">&nbsp;</span>
    <a href="#myTarget">My text</a>
</h3>

真实页面示例:

使用 bootDoc std.array.uninitializedArray文档

注意:

它不适用于IE 6。

 h1, h2, h3, h4, h5, h6 {
   scroll-margin-top: 80px;
 }

从 React 文档中得到了这个想法。

对我来说最有效的事情是这样做:

  1. 将指定的 ID(您希望在 URL 中的内容)提供给所需元素中的其他元素。
  2. 将该新元素设为绝对元素,并将其移动到所需元素上方的 X 像素,其中 X 是固定标题的高度。

其他人都给出了CSS答案,但问题要求JS进行

@assmmahmud的答案只需一个小调整即可:gotoSpecificPosition需要在第一个语句中更改为offsetAnchor。

这对于调整粘性标头的所有 id 链接非常有帮助。

/* go to specific position if you load the page directly from address bar */
var navbarHeight = document.getElementById('mynavbar').clientHeight;
function offsetAnchor() {
  if (window.location.hash.length !== 0) {
    window.scrollTo(window.scrollX, window.scrollY - navbarHeight );
  }
}
/* Captures click events on all anchor tag with a hash tag */
$(document).on('click', 'a[href^="#"]', function(event) {
  // Click events are captured before hashchanges. Timeout
  // causes offsetAnchor to be called after the page jump.
  window.setTimeout(function() {
    offsetAnchor();
  }, 0);
});
window.setTimeout(offsetAnchor, 0);

不幸的是(至少使用 Firefox)填充和边距在这里都没有帮助(将它们放在包含除菜单栏之外的所有内容的"主"div 上); 滚动到锚点总是将其放在页面的最顶部,固定元素该死。

我认为您将不得不遵循您最初的想法,但请记住,通过使用委派,您可以只设置一个处理程序,该处理程序将处理菜单栏中的所有链接,包括动态添加的链接。

使用纯javascript,您可以执行以下操作。它将侦听所有锚标记的点击事件,并滚动到页面中所需的位置(它正在使用jquery):

/* go to specific position if you load the page directly from address bar */
var navbarHeight = document.getElementById('mynavbar').clientHeight;
function gotoSpecificPosition() {
  if (window.location.hash.length !== 0) {
    window.scrollTo(window.scrollX, window.scrollY - navbarHeight );
  }
}
/* Captures click events on all anchor tag with a hash tag */
$(document).on('click', 'a[href^="#"]', function(event) {
  // Click events are captured before hashchanges. Timeout
  // causes offsetAnchor to be called after the page jump.
  window.setTimeout(function() {
    offsetAnchor();
  }, 0);
});
window.setTimeout(offsetAnchor, 0);

上面的代码将处理所有技巧。

尝试在页面顶部放置一个填充,以占据菜单栏后面的区域。像这样:padding-top:80px;(你应该放置菜单栏的高度,而不是80px)。