偏移 html 锚点以调整固定标题

IT技术 javascript html css anchor offset
2021-02-01 05:56:45

我正在努力清理我的锚的工作方式。我有一个固定在页面顶部的标题,因此当您链接到页面其他位置的锚点时,页面会跳转,因此锚点位于页面顶部,将内容留在固定标题后面(我希望这就说得通了)。我需要一种方法来将锚点从标题的高度偏移 25 像素。我更喜欢 HTML 或 CSS,但 Javascript 也可以接受。

6个回答

您可以只使用 CSS 而不使用任何 javascript。

给你的主播上课:

<a class="anchor" id="top"></a>

然后,您可以通过将锚定为块元素并对其进行相对定位,将锚定为比它实际出现在页面上的位置高或低的偏移量。-250px 将定位点向上 250px

a.anchor {
    display: block;
    position: relative;
    top: -250px;
    visibility: hidden;
}
@harpo:好主意,但行不通。在 Chrome 40 中尝试过。
2021-03-12 05:56:45
我们不应该再使用没有 href 属性的标签。相反,我们假设在标题/部分/等中使用 id 标签作为锚定文本。那有什么解决办法呢?
2021-03-15 05:56:45
这是更好的答案,因为它不依赖于位置设置为相对的父元素。感谢您发布此信息。
2021-03-24 05:56:45
喜欢你的解决方案!它似乎不适用于 IE7。无论如何,我打算从现在开始忽略IE7用户......
2021-03-27 05:56:45
如果你想让它对可见元素起作用,你也可以使用一个伪元素,一个 la.thing-with-anchor:before { content: ''; display: block; position: relative; width: 0; height: 5em; margin-top: -5em } 显示块和相对位置是必不可少的。
2021-03-30 05:56:45

我找到了这个解决方案:

<a name="myanchor">
    <h1 style="padding-top: 40px; margin-top: -40px;">My anchor</h1>
</a>

这不会在内容中造成任何差距,锚链接的效果非常好。

由于隐藏的填充/边距,位于 <h1> 上方的元素将不可点击。我最终使用了 Ian Clack 的 jQuery 解决方案,效果很好。
2021-03-18 05:56:45
工作得很好。我创建了一个特殊的 CSS 锚点类并将它附加到我的锚点:<a class="anchor" name="foo"></a>。谢谢。
2021-03-31 05:56:45
导航中的指标仍然有问题。因此,如果您向下滚动页面,则活动导航项不会切换,直到您滚动经过锚点目标。
2021-04-01 05:56:45
我想我想通了: h2[id], h3[id], h4[id], a[name] { padding-top: XXpx; 填充底部:XXpx;它适用于所有带有 ID 的 h2、h3、h4 标签以及命名锚点。
2021-04-01 05:56:45
您将如何使其与使用元素 ID 的锚点一起使用,即 <h1 id="smth">Text</h1>...<a href="#smth">Link</a>?
2021-04-03 05:56:45

我也在寻找解决方案。就我而言,这很容易。

我有一个包含所有链接的列表菜单:

<ul>
<li><a href="#one">one</a></li>
<li><a href="#two">two</a></li>
<li><a href="#three">three</a></li>
<li><a href="#four">four</a></li>
</ul>

下面是它应该去的标题。

<h3>one</h3>
<p>text here</p>

<h3>two</h3>
<p>text here</p>

<h3>three</h3>
<p>text here</p>

<h3>four</h3>
<p>text here</p>

现在,因为我的页面顶部有一个固定菜单,所以我不能让它进入我的标签,因为它会在菜单后面。

相反,我在我的标签中放置了一个具有正确 id 的 span 标签。

<h3><span id="one"></span>one</h3>

现在使用 2 行 CSS 来正确定位它们。

h3{ position:relative; }
h3 span{ position:absolute; top:-200px;}

更改顶部值以匹配固定标题(或更多)的高度。现在我假设这也适用于其他元素。

这非常有效,并且避免了我使用其他技术遇到的一些问题,例如在使用设置 padding-top 的 h2 标签时。
2021-03-21 05:56:45
span 可以替换为 a
2021-03-27 05:56:45
杰出的。完美运行。+1
2021-04-04 05:56:45
这肯定会得到复选标记。
2021-04-05 05:56:45
我喜欢这个解决方案
2021-04-05 05:56:45

由于这是一个演示问题,纯 CSS 解决方案将是理想的。然而,这个问题是在 2012 年提出的,虽然已经提出了相对定位/负边距的解决方案,但这些方法似乎相当笨拙,会产生潜在的流量问题,并且无法动态响应 DOM/视口的变化。

考虑到这一点,我相信使用 JavaScript仍然(2017 年 2 月)最好的方法。下面是一个 vanilla-JS 解决方案,它将响应锚点点击并在加载时解析页面哈希(参见 JSFiddle).getFixedOffset()如果需要动态计算,请修改方法。如果您使用 jQuery,这里有一个改进的解决方案,它具有更好的事件委托和平滑滚动

(function(document, history, location) {
  var HISTORY_SUPPORT = !!(history && history.pushState);

  var anchorScrolls = {
    ANCHOR_REGEX: /^#[^ ]+$/,
    OFFSET_HEIGHT_PX: 50,

    /**
     * Establish events, and fix initial scroll position if a hash is provided.
     */
    init: function() {
      this.scrollToCurrent();
      window.addEventListener('hashchange', this.scrollToCurrent.bind(this));
      document.body.addEventListener('click', this.delegateAnchors.bind(this));
    },

    /**
     * Return the offset amount to deduct from the normal scroll position.
     * Modify as appropriate to allow for dynamic calculations
     */
    getFixedOffset: function() {
      return this.OFFSET_HEIGHT_PX;
    },

    /**
     * If the provided href is an anchor which resolves to an element on the
     * page, scroll to it.
     * @param  {String} href
     * @return {Boolean} - Was the href an anchor.
     */
    scrollIfAnchor: function(href, pushToHistory) {
      var match, rect, anchorOffset;

      if(!this.ANCHOR_REGEX.test(href)) {
        return false;
      }

      match = document.getElementById(href.slice(1));

      if(match) {
        rect = match.getBoundingClientRect();
        anchorOffset = window.pageYOffset + rect.top - this.getFixedOffset();
        window.scrollTo(window.pageXOffset, anchorOffset);

        // Add the state to history as-per normal anchor links
        if(HISTORY_SUPPORT && pushToHistory) {
          history.pushState({}, document.title, location.pathname + href);
        }
      }

      return !!match;
    },

    /**
     * Attempt to scroll to the current location's hash.
     */
    scrollToCurrent: function() {
      this.scrollIfAnchor(window.location.hash);
    },

    /**
     * If the click event's target was an anchor, fix the scroll position.
     */
    delegateAnchors: function(e) {
      var elem = e.target;

      if(
        elem.nodeName === 'A' &&
        this.scrollIfAnchor(elem.getAttribute('href'), true)
      ) {
        e.preventDefault();
      }
    }
  };

  window.addEventListener(
    'DOMContentLoaded', anchorScrolls.init.bind(anchorScrolls)
  );
})(window.document, window.history, window.location);
@tom10 我想你只需要让选择器更具体,要么通过使用a:not(.not-anchor)(或不太容易混淆的名称)将锚点列入黑名单,然后确保你的折叠/轮播库将这些类添加到它们的锚点中。如果您使用的是 jQuery UI 或 Bootstrap,我想他们会添加一些您可以参考的其他类。
2021-03-13 05:56:45
如果您在同一个锚点上连续单击 2 次(从带有锚点链接的菜单中),则第二次单击效果不佳。
2021-03-14 05:56:45
效果很好,但对于 jquery 1.7+,使用 $("a").on("click",... 而不是 $("a").live("click",...
2021-03-23 05:56:45
不错的评论,我会更新:) - 顺便说一句,它也应该如此,$("body").on("click", "a"...因为它可能需要为通过脚本添加到文档中的锚点工作(因此我为什么使用.live
2021-04-01 05:56:45
另外,值得注意的是,这会与其他 href/id 对混淆,如折叠、轮播等......有没有简单的方法来解决这个问题?
2021-04-07 05:56:45

FWIW这对我有用:

[id]::before {
  content: '';
  display: block;
  height:      75px;
  margin-top: -75px;
  visibility: hidden;
}
我将其包装在媒体查询中,因此它仅适用于具有固定导航的中型和大型屏幕。
2021-03-14 05:56:45
这可能有效,但它会与标题之前的内容重叠。
2021-03-22 05:56:45
我不完全理解为什么会这样,但是我 +1。其他任何一个都不像这个那样容易实现或工作得很好。:-)
2021-03-29 05:56:45
有人可以解释为什么会这样吗?
2021-04-04 05:56:45
你这个男人!很好的解决方案。
2021-04-08 05:56:45