协慌网

登录 贡献 社区

抵消 html 锚点以调整固定标题

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

答案

您可以在没有任何 JavaScript 的情况下使用 CSS。

给你的锚一个班:

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

然后,您可以将锚点设置为高于或低于页面实际显示位置的偏移量,方法是将其设置为块元素并相对定位。 -250px 将锚定位置为 250px

a.anchor {
    display: block;
    position: relative;
    top: -250px;
    visibility: hidden;
}

我找到了这个解决方案

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

这不会在内容中产生任何差距,并且锚链接工作非常好。

由于这是演示的关注点,纯 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);