我正在努力清理我的锚的工作方式。我有一个固定在页面顶部的标题,所以当你链接到页面其他地方的锚时,页面跳转,锚位于页面顶部,留下固定标题后面的内容(我希望这是有意义的)。我需要一种方法来抵消锚的25px从头部的高度。我更喜欢HTML或CSS,但Javascript也可以接受。


当前回答

对于现代浏览器,只需将CSS3:target选择器添加到页面。这将自动应用于所有的锚。

:target {
    display: block;    
    position: relative;     
    top: -100px;
    visibility: hidden;
}

其他回答

我在一个TYPO3网站上遇到了这个问题,其中所有的“内容元素”都用类似这样的东西包装:

<div id="c1234" class="contentElement">...</div>

我改变了渲染,所以它是这样渲染的:

<div id="c1234" class="anchor"></div>
<div class="contentElement">...</div>

这个CSS:

.anchor{
    position: relative;
    top: -50px;
}

固定的topbar是40px高,现在锚再次工作,并在topbar下10px开始。

这种技术的唯一缺点是你不能再使用:target。

你可以使用a[name]:not([href]) css选择器在没有ID的情况下实现这一点。这仅仅是查找有名称且没有href的链接,例如<a name="anc1"></a>

一个示例规则可能是:

a[name]:not([href]){
    display: block;    
    position: relative;     
    top: -100px;
    visibility: hidden;
}

我的解决方案结合了CMS的目标和前选择器。其他技术不考虑锚中的文本。调整高度和负边距到你需要的偏移量…

:target::before {
    content: '';
    display: block;
    height:      180px;
    margin-top: -180px;
}

@AlexanderSavin的解决方案在WebKit浏览器中对我来说很棒。

另外,我不得不使用:target伪类,它将样式应用到选定的锚来调整FF, Opera和IE9中的填充:

a:target {
  padding-top: 40px
}

注意,这种风格不适合Chrome / Safari,所以你可能不得不使用css-hacks,条件注释等。

我还想注意到,Alexander的解决方案工作,因为目标元素是内联的。如果你不想要链接,你可以简单地改变显示属性:

<div id="myanchor" style="display: inline">
   <h1 style="padding-top: 40px; margin-top: -40px;">My anchor</h1>
</div>

由于这是表示的问题,纯CSS解决方案将是理想的。然而,这个问题是在2012年提出的,尽管已经提出了相对定位/负边际的解决方案,但这些方法看起来相当俗气,会产生潜在的流量问题,并且不能动态响应DOM /视口的变化。

考虑到这一点,我相信使用JavaScript仍然是(2017年2月)最好的方法。下面是一个香草- 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);