Bootstrap词缀导航栏用于带有scrollspy和页面锚点的单页 [英] Bootstrap affix navbar for single page with scrollspy and page anchors

查看:91
本文介绍了Bootstrap词缀导航栏用于带有scrollspy和页面锚点的单页的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是一个页面,其中的导航栏仅链接到本地​​锚点.
导航栏位于标题之后,但在向下滚动时会停留在顶部.

This is for a single page, with a navbar that links to local anchors only.
The navbar comes after a header, but sticks to top when scrolling down.

您可以在github页面上查看

You can see how it works on github pages

但是链接/锚点存在两个偏移问题:

But I've got two offset problems with link/anchors:

  • 只要您不滚动,锚点就会被导航栏偏移并掩盖.
  • 粘贴导航栏后,以下链接将按预期运行,但第一个链接无效.

由于页边距阻止标题从顶部开始,因此页边空白破坏了布局:

A body margin breaks the layout as it prevents the header from beginning right at the top:

body {
    margin-top: 65px;
}

我尝试了以下部分的边距/填充操作:

I've tried without success to play with margin/padding for the sections:

section {
    padding-top: 65px;
    margin-top: -65px; 
}

这是 html

  • 有什么办法解决这个问题吗?
  • 可以用纯CSS解决吗?
  • 还是我需要一些js修补程序才能解决词缀?
  • 推荐答案

    我认为您的问题仅与词缀有关.我在3种情况下发现了问题:

    I think your problem has only to do with the affix. I found a problem in 3 situations:

    1. 不滚动并单击链接
    2. 点击第一个链接
    3. scoll,单击第一个链接,然后单击另一个链接.

    在这三种情况下,您从未应用词缀的位置单击到已应用词缀的位置.

    In this three situation you click from an position where you affix is not applied to a position where your affix has been applied.

    单击将目标锚点滚动到页面顶部并在其后应用词缀(将导航栏的位置设置为固定)会发生什么.结果导航栏与内容重叠.

    What happens your click scrolls the target anchor to the top of the page and applies the affix (set navbar's position to fixed) after this. Result the navbar overlaps the content.

    我认为您不能仅使用CSS来解决此问题.我认为您为该部分添加页边距/填充的解决方案是正确的,但是您必须在词缀后应用页边距.

    I don't think you could fix this with css only. I think your solution of adding a margin / padding to the section will be right, but you will have to apply the margin after the affix.

    我尝试过类似的事情:

    var tmp = $.fn.affix.Constructor.prototype.checkPosition;
    var i = 0;
    var correct = false
    $.fn.affix.Constructor.prototype.checkPosition = function () {
      $('#content').css('margin-top','0');
      tmp.call(this);
    
      if(i%2!=0 && $(window).scrollTop()<443){correct=true}
      if(i%2==0 && correct){$('#content').css('margin-top','83px').trigger('create'); correct=false}
      i++;
    }
    

    这感觉很复杂,现在似乎只能在Firefox上使用.

    This feels to complex and also only seems to work on firefox now.

    更新

    我认为我可以通过覆盖完整的词缀checkPosition函数来解决您的问题:

    I think i could fix your problem by overwritting the complete affix checkPosition function:

    $.fn.affix.Constructor.prototype.checkPosition = function () 
    {
        if (!this.$element.is(':visible')) return
    
        var scrollHeight = $(document).height()
        var scrollTop    = this.$window.scrollTop()
        var position     = this.$element.offset()
        var offset       = this.options.offset
        var offsetTop    = offset.top
        var offsetBottom = offset.bottom
        if(scrollTop==378) 
        {
        this.$window.scrollTop('463');
        scrollTop==463;
        }
        if (typeof offset != 'object')         offsetBottom = offsetTop = offset
        if (typeof offsetTop == 'function')    offsetTop    = offset.top()
        if (typeof offsetBottom == 'function') offsetBottom = offset.bottom()
    
        var affix = this.unpin   != null && (scrollTop + this.unpin <= position.top) ? false :
                    offsetBottom != null && (position.top + this.$element.height() >= scrollHeight - offsetBottom) ? 'bottom' :
                    offsetTop    != null && (scrollTop <= offsetTop) ? 'top' : false
        console.log(scrollTop + ':' + offsetTop);
    
        if(scrollTop > offsetTop) {$('#content').css('margin-top','83px'); console.log('margin') }
        else{$('#content').css('margin-top','0');}
        if (this.affixed === affix) return
    
        if (this.unpin) this.$element.css('top', '')
    
        this.affixed = affix
        this.unpin   = affix == 'bottom' ? position.top - scrollTop : null
    
        this.$element.removeClass('affix affix-top affix-bottom').addClass('affix' + (affix ? '-' + affix : ''))
    
        if (affix == 'bottom') {
          this.$element.offset({ top: document.body.offsetHeight - offsetBottom - this.$element.height() })
        }
    }
    

    有些值已经过硬编码(现在),因此此功能仅适用于github页面上的示例.

    Some values are hard coded (now) so this function only will work for your example on github pages.

    演示: http://bootply.com/81336

    在github页面上,您使用jQuery和Bootstrap的旧"版本.您无需为scrollspy设置偏移量.您不必调用$('#navbar').scrollspy();,因为您已经使用数据属性设置了scrollspy.

    On github pages you use "old" versions of jQuery and Bootstrap. You don't need to set an offset for the scrollspy. You don't have to call $('#navbar').scrollspy(); also cause you already set the scrollspy with data attributes.

    另请参阅: https://github.com/twbs/bootstrap/issues/10670

    删除此硬编码值

    单击内部链接(以#{id}开头)时,id = {id}的锚点将滚动到视口顶部. 在这种情况下,将有一个固定的导航栏(词缀),因此锚点应滚动到顶部减去导航栏的高度. 导航栏的高度将为85px(品牌图片的63像素+边框的2像素+ .navbarheader的20 px的边距底部)

    When clicking an internal link (start with #{id}) the anchor with id={id} will be scrolled to the top of the viewport. In this case there will be a fixed navbar (affix) so the anchor should scroll to the top minus the height of the navbar. The height of the navbar will be 85px (63 pixels of the brand image + 2 pixels of the border + the margin-bottom of 20 px of the .navbarheader)

    此值将在此处使用:

    if(scrollTop > offsetTop) {$('#content').css('margin-top','83px'); console.log('margin') }
    else{$('#content').css('margin-top','0');}
    

    我用过83(可能看起来更好吗?). 因此83可以替换为:var navbarheight = $('#nav').innerHeight()

    I have used 83 (may look better?). So the 83 can be replaced with: var navbarheight = $('#nav').innerHeight()

    那么我们有这些:

    if(scrollTop==378) 
    {
    this.$window.scrollTop('463');
    scrollTop==463;//typo?? make no sense
    } 
    

    (第一个)链接将锚点滚动到没有词缀的顶部 已应用(在data-offset-top ="443"以下)固定高度 导航栏未用于计算,因此该点将为443-85 (navbarheight)=378.此代码可以替换为.

    The (first) link scrolls the anchor to the top where the affix is not applied yet (below data-offset-top="443") the height of your fixed navbar is not used in calculacting so this point will be 443 - 85 (navbarheight) = 378. This code could be replace with.

    if(scrollTop==(443-navbarheight)) 
    {
    this.$window.scrollTop(scrollTop+navbarheight);
    }
    

    注释443现在仍将被硬编码.它也硬编码在您的 带有affix-top的html.

    Note 443 now still will be hardcoded. It is also hardcoded in your html with affix-top.

    当心用上述值替换值将不起作用.这 (af)固定和不固定之间的情况将随着每次滚动而改变 行动. if(scrollTop==378)部分是技巧而不是解决方案.它 解决滚动高度<数据偏移量最高.我们不能 应用整个范围,在这种情况下,用户永远无法滚动 返回顶部(this.$ window.scrollTop一次又一次地向后滚动他).

    Watch out Replacing the values with the above won't work. The situation between (af)fixed and not will change for every scroll action. The part if(scrollTop==378) is a trick not a solution. It solves the situation for scrollheight < data-offset-top. We could not apply the whole range, case in that case the user can't never scroll back to the top (this.$window.scrollTop scrolls him back again and again).

    navbarheight的计算也很棘手.当导航栏 固定$('#nav').innerHeight()/高度将返回85(包括 保证金).绝对位置是65.

    Also the calculation of navbarheight will be tricky. When the navbar is fixed $('#nav').innerHeight() / height will return 85 (including the margin). In the absolute position this will be 65.

    这篇关于Bootstrap词缀导航栏用于带有scrollspy和页面锚点的单页的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆