javascript - 锚点w3c - 锚点实现




抵消一个html锚点以调整固定标题 (19)

你可以做到这一点没有js和没有改变HTML。 这只是CSS而已。

a[id]:before {
    content:"";
    display:block;
    height:50px;
    margin:-30px 0 0;
}

这将在每个带有id的a-tag之前附加一个伪元素。 调整值以匹配标题的高度。

这个问题在这里已经有了答案:

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


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

我还必须使用:目标伪类,它将选择的锚点的样式应用于FFOperaIE9调整填充:

a:target {
  padding-top: 40px
}

请注意,这种风格不适用于Chrome / Safari因此您可能必须使用css-hacks,条件注释等。

另外我想注意的是,亚历山大的解决方案是有效的,因为目标元素是inline 。 如果你不想链接,你可以简单地改变display属性:

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

从@Jan得到的优秀答案的另一个转折是将它加入到使用jQuery(或MooTools)的#uberbar固定头文件中。 ( http://davidwalsh.name/persistent-header-opacity

我已经调整了代码,所以内容的顶部总是低于固定标题下面,并且再次从@Jan添加锚点,以确保锚点始终位于固定标题下方。

CSS:

#uberbar { 
    border-bottom:1px solid #0000cc; 
    position:fixed; 
    top:0; 
    left:0; 
    z-index:2000; 
    width:100%;
}

a.anchor {
    display: block;
    position: relative;
    visibility: hidden;
}

jQuery(包括调整#uberbar和锚点方法:

<script type="text/javascript">
$(document).ready(function() {
    (function() {
        //settings
        var fadeSpeed = 200, fadeTo = 0.85, topDistance = 30;
        var topbarME = function() { $('#uberbar').fadeTo(fadeSpeed,1); }, topbarML = function() { $('#uberbar').fadeTo(fadeSpeed,fadeTo); };
        var inside = false;
        //do
        $(window).scroll(function() {
            position = $(window).scrollTop();
            if(position > topDistance && !inside) {
                //add events
                topbarML();
                $('#uberbar').bind('mouseenter',topbarME);
                $('#uberbar').bind('mouseleave',topbarML);
                inside = true;
            }
            else if (position < topDistance){
                topbarME();
                $('#uberbar').unbind('mouseenter',topbarME);
                $('#uberbar').unbind('mouseleave',topbarML);
                inside = false;
            }
        });
        $('#content').css({'margin-top': $('#uberbar').outerHeight(true)});
        $('a.anchor').css({'top': - $('#uberbar').outerHeight(true)});
    })();
});
</script>

最后是HTML:

<div id="uberbar">
    <!--CONTENT OF FIXED HEADER-->
</div>
....
<div id="content">
    <!--MAIN CONTENT-->
    ....
    <a class="anchor" id="anchor1"></a>
    ....
    <a class="anchor" id="anchor2"></a>
    ....
</div>

也许这对于喜欢#uberbar褪色混合头的人是有用的!


你也可以添加一个跟随attr的锚点:

(text-indent:-99999px;)
visibility: hidden;
position:absolute;
top:-80px;    

并给父容器一个相对位置。

对我来说很完美。


借用这个链接给出的答案中的一些代码(没有指定作者),可以在锚点上包含一个很好的平滑滚动效果,同时使其停留在锚点上方-60px处,适合安装在固定引导程序的下方栏(需要jQuery):

$(".dropdown-menu a[href^='#']").on('click', function(e) {
   // prevent default anchor click behavior
   e.preventDefault();

   // animate
   $('html, body').animate({
       scrollTop: $(this.hash).offset().top - 60
     }, 300, function(){
     });
});

如果您的锚点是表格元素或表格(行或单元格),上述方法不能很好地工作。

我必须使用javascript并绑定到窗口hashchange事件来解决这个( demo ):

function moveUnderNav() {
    var $el, h = window.location.hash;
    if (h) {
        $el = $(h);
        if ($el.length && $el.closest('table').length) {
            $('body').scrollTop( $el.closest('table, tr').position().top - 26 );
        }
    }
}

$(window)
    .load(function () {
        moveUnderNav();
    })
    .on('hashchange', function () {
        moveUnderNav();
    });

*注意: hashchange事件在所有浏览器中都不可用。


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

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

您可以使用a[name]:not([href]) css选择器来实现此功能。 这只是寻找与名称和无href链接,例如<a name="anc1"></a>

示例规则可能是:

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

我发现这个解决方案:

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

这并不会在内容上产生任何差距,而且链接链接非常好。


我在一个TYPO3网站上面对这个问题,所有的“内容元素”都是用类似的东西包装的:

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

我改变了渲染,使它呈现如下:

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

而这个CSS:

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

固定顶栏为40px高,现在锚再次工作,并在顶栏下开始10px。

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


我在每个h1元素之前添加了40px高度的.vspace元素。

<div class="vspace" id="gherkin"></div>
<div class="page-header">
  <h1>Gherkin</h1>
</div>

在CSS中:

.vspace { height: 40px;}

它工作得很好,空间不是窒息。


我的解决方案将我们CMS的目标和选择器结合在一起。 其他技术不考虑锚中的文本。 将高度和负边距调整为需要的偏移量...

:target:before {
    content: "";
    display: inline-block;
    height: 180px;
    margin: -180px 0 0;
}

改变位置属性的解决方案并不总是可能的(它可以破坏布局),因此我建议:

HTML:

<a id="top">Anchor</a>

CSS:

#top {
    margin-top: -250px;
    padding-top: 250px;
}

用这个:

<a id="top">&nbsp;</a>

最大限度地减少重叠,并设置字体大小为1px。 空锚在某些浏览器中不起作用。


来自Alexander Savin的纯CSS解决方案:

a[name] {
  padding-top: 40px;
  margin-top: -40px;
  display: inline-block; /* required for webkit browsers */
}

或者,如果目标仍在屏幕外,可能需要添加以下内容:

  vertical-align: top;

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

而不是有一个固定位置的导航栏与页面内容的其余部分不一致(整个页面正文可滚动),请考虑改为使用静态导航栏不可滚动的正文,然后将页面内容放入下面是绝对定位的可滚动div。

也就是说,有这样的HTML ...

<div class="static-navbar">NAVBAR</div>
<div class="scrollable-content">
  <p>Bla bla bla</p>
  <p>Yadda yadda yadda</p>
  <p>Mary had a little lamb</p>
  <h2 id="stuff-i-want-to-link-to">Stuff</h2>
  <p>More nonsense</p>
</div>

...和CSS这样的:

.static-navbar {
  height: 100px;
}
.scrollable-content {
  position: absolute;
  top: 100px;
  bottom: 0;
  overflow-y: scroll;
  width: 100%;
}

这以直截了当的方式达到了预期的效果。 这和上面提出的一些聪明的CSS hack之间的行为唯一的区别在于,滚动条(在呈现一个的浏览器中)将被附加到内容div而不是整个页面的高度。 你可能会也可能不会考虑这个理想。

这里有一个JSFiddle展示了这个动作。


这是我们在网站上使用的解决方案。 将headerHeight变量调整为任何标题高度。 将js-scroll类添加到应该单击滚动的锚点上。

// SCROLL ON CLICK
// --------------------------------------------------------------------------
$('.js-scroll').click(function(){
    var headerHeight = 60;

    $('html, body').animate({
        scrollTop: $( $.attr(this, 'href') ).offset().top - headerHeight
    }, 500);
    return false;
});

这需要从以前的答案中的许多元素,并结合成一个小(194字节缩小)的匿名jQuery函数。 调整fixedElementHeight作为菜单或阻挡元素的高度。

    (function($, window) {
        var adjustAnchor = function() {

            var $anchor = $(':target'),
                    fixedElementHeight = 100;

            if ($anchor.length > 0) {

                $('html, body')
                    .stop()
                    .animate({
                        scrollTop: $anchor.offset().top - fixedElementHeight
                    }, 200);

            }

        };

        $(window).on('hashchange load', function() {
            adjustAnchor();
        });

    })(jQuery, window);

如果您不喜欢动画,请替换

$('html, body')
     .stop()
     .animate({
         scrollTop: $anchor.offset().top - fixedElementHeight
     }, 200);

有:

window.scrollTo(0, $anchor.offset().top - fixedElementHeight);

Uglified版本:

 !function(o,n){var t=function(){var n=o(":target"),t=100;n.length>0&&o("html, body").stop().animate({scrollTop:n.offset().top-t},200)};o(n).on("hashchange load",function(){t()})}(jQuery,window);

除了Ziav的回答(感谢Alexander Savin)之外,我还需要使用旧学校的<a name="...">...</a>因为我们使用的是<div id="...">...</div>用于我们的代码中的另一个目的。 我在使用display: inline-block遇到了一些显示问题display: inline-block - 每个<p>元素的第一行display: inline-block为稍微右移(在Webkit和Firefox浏览器上)。 我最终尝试了其他display值并display: table-caption完美地适用于我。

.anchor {
  padding-top: 60px;
  margin-top: -60px;
  display: table-caption;
}






offset