【问题标题】:Bootstrap affix navbar for single page with scrollspy and page anchors带有scrollspy和页面锚点的单页引导附加导航栏
【发布时间】:2013-09-14 08:07:58
【问题描述】:

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

你可以看到它是如何工作的on github pages

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

  • 只要您不滚动,锚点就会被导航栏偏移和遮住。
  • 粘贴导航栏后,以下链接将按预期工作,但不是第一个链接。

正文页边距会破坏布局,因为它会阻止标题从顶部开始:

body {
    margin-top: 65px;
}

我尝试过为这些部分使用边距/填充但没有成功:

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

这里是html 和css

  • 知道如何解决这个问题吗?
  • 用纯css能解决吗?
  • 或者我需要一些 js 修复来解释词缀吗?

【问题讨论】:

标签: single-page-application navbar twitter-bootstrap-3 scrollspy affix


【解决方案1】:

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

  1. 没有滚动和点击链接
  2. 点击第一个链接
  3. scoll,单击第一个链接,然后单击另一个链接。

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

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

我认为你不能只用 css 来解决这个问题。我认为您向该部分添加边距/填充的解决方案是正确的,但您必须在词缀之后应用边距。

我尝试了类似的方法:

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 上运行。

更新

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

$.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 页面上的示例。

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

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

另见:https://github.com/twbs/bootstrap/issues/10670

移除此硬编码值

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

这里会用到这个值:

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

我用过 83(可能看起来更好?)。 所以83可以换成:var navbarheight = $('#nav').innerHeight()

然后我们有这些:

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

(第一个)链接将锚点滚动到没有词缀的顶部 尚未应用(低于 data-offset-top="443")固定的高度 navbar 不用于计算,所以这一点将是 443 - 85 (navbarheight) = 378。此代码可以替换为。

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

Note 443 现在仍将是硬编码的。它也被硬编码在你的 html 带有 affix-top。

注意用上面的值替换是行不通的。这 (af)fixed 和 not 之间的情况对于每个滚动都会改变 行动。 if(scrollTop==378) 部分是技巧而不是解决方案。它 解决了 scrollheight

navbarheight 的计算也很棘手。当导航栏 固定 $('#nav').innerHeight() / 高度将返回 85(包括 边距)。在绝对位置上,这将是 65。

【讨论】:

  • 它有效,谢谢。我只是看看如何删除硬编码值。有什么想法吗?
  • 查看我的答案更新。事实上,这将是非常复杂的。为此,您应该计算滚动起始位置和结束位置的位置/高度
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-04-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多