3

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.

You can see how it works on github pages

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

  • as long as you don't scroll, the anchors are offset and masked by the navbar.
  • once the navbar is affixed, the following links work as intended but not the first one.

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

Here are the html and css

  • Any idea how to fix that?
  • Can it be solved with pure css?
  • Or do I need some js fix to account for the affix?
4

1 回答 1

2

我认为您的问题仅与词缀有关。我在 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")固定导航栏的高度未用于计算,因此该点将为 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 < data-offset-top 的情况。我们不能应用整个范围,在这种情况下,用户不能永远滚动回顶部(this.$window.scrollTop 一次又一次地滚动他)。

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

于 2013-09-16T18:25:17.393 回答