带有滚动间谍和页面锚点的单页 Bootstrap 附加导航栏 [英] Bootstrap affix navbar for single page with scrollspy and page anchors

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

问题描述

这适用于单个页面,导航栏仅链接到本地​​锚点.
导航栏出现在标题之后,但向下滚动时会停留在顶部.

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 页面上查看它的工作原理

但是我有两个链接/锚点偏移问题:

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; 
}

这里是 htmlcss

  • 知道如何解决这个问题吗?
  • 纯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.您不需要为滚动间谍设置偏移量.您不必调用 $('#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} 的锚点将滚动到视口的顶部.在这种情况下,将有一个固定的导航栏(词缀),因此锚点应滚动到顶部减去导航栏的高度.导航栏的高度为 85 像素(品牌形象的 63 像素 + 边框的 2 像素 + .navbarheader 的 20 像素的边距底部)

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);
}

Note 443 现在仍然是硬编码的.它也被硬编码在你的带有前缀的 html.

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

当心 用上面的替换值是行不通的.这(af)fixed 和 not 之间的情况会随着每个滚动而改变行动.if(scrollTop==378) 部分是一个技巧而不是解决方案.它解决了 scrollheight <;数据偏移量顶部.我们不能应用整个范围,在这种情况下用户不能永远滚动回到顶部(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).

导航栏高度的计算也很棘手.当导航栏固定 $('#nav').innerHeight()/height 将返回 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 附加导航栏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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