33

我想使用 Bootstraps 文档 ( http://getbootstrap.com/javascript/#affix ) 中描述的 Affix 方法,但是我想在滚动到页面顶部后修复的导航栏可以有不同的偏移量值取决于它上面的内容。

这是导航栏的示例:

<div class="navbar navbar-default" data-spy="affix" data-offset-top="200">
  <ul class="nav navbar-nav">
    <li class="active"><a href="#">Link</a></li>
    <li><a href="#">Link 1</a></li>
    <li><a href="#">Link 2</a></li>
  </ul>
</div>

如您所见,data-offset-top当前设置为 200。如果上面的内容是 200px 高,这可以正常工作,但上面的内容是动态的,因此此导航栏上方的高度并不总是相同的。我怎样才能使淡水河谷data-offset-top充满活力?

我猜我将不得不使用 javascript 的方式来做这件事,但我不确定。

4

7 回答 7

44

您可以使用 jQuery 获取高于navbar. 例如:

$('#nav').affix({
      offset: {
        top: $('header').height()
      }
}); 

工作演示:http ://bootply.com/69848

在某些情况下,还必须计算 offset.bottom 以确定何时“取消附加”元素。这是一个 affix-bottom 的例子

于 2013-09-09T16:39:56.110 回答
21

我对这种工作方式感到非常沮丧,每次都进行一些自定义计算并在所需词缀上方的元素高度上建立偏移量。

这是最好的词缀。

普通的 boostrap 词缀不考虑项目的自然偏移顶部位置,您必须手动将其作为属性传递。这会解决这个问题,并解释窗口调整大小时偏移顶部的变化。

var $attribute = $('[data-smart-affix]');
$attribute.each(function(){
  $(this).affix({
    offset: {
      top: $(this).offset().top,
    }
  })
})
$(window).on("resize", function(){
  $attribute.each(function(){
    $(this).data('bs.affix').options.offset.top = $(this).offset().top
  })
})

我也在代码审查上发布了这个。

不要忘记将data-smart-affix属性添加到您的 affix 元素

试试这个示例代码:https
://jsfiddle.net/NabiKAZ/qyrauogw/ (在这个示例中,红色部分的高度可能是 100px 或 200px 或 300px 的窗口宽度差异,因此需要data-offset-top在滚动时进行差异。)

于 2015-03-19T15:43:31.287 回答
3

ThomasReggi 的 data-smart-affix 在某些极端情况下(在调整文档大小或附加列太高时)对我不起作用。但它给了我一个简单的想法:在附加内容之前添加一个空元素,并使用它来获取偏移量。调整大小时效果很好。

当我这样做时,我还将元素的宽度设置为原始父级中的自然宽度。这是我的解决方案:

$('[data-affix-after]').each( function() {
  var elem = $(this);
  var parent_panel = elem.parent();
  var prev = $( elem.data('affix-after') );

  if( prev.length != 1 ) {
    /* Create a new element immediately before. */
    prev = elem.before( '<div></div>' ).prev();
  }

  var resizeFn = function() {
      /* Set the width to it's natural width in the parent. */
      var sideBarNavWidth = parent_panel.width()
          - parseInt(elem.css('paddingLeft'))
          - parseInt(elem.css('paddingRight'))
          - parseInt(elem.css('marginLeft'))
          - parseInt(elem.css('marginRight'))
          - parseInt(elem.css('borderLeftWidth'))
          - parseInt(elem.css('borderRightWidth'));
      elem.css('width', sideBarNavWidth);

      elem.affix({
          offset: {
              top: prev.offset().top + prev.outerHeight(true),
              bottom: $('body>footer').outerHeight(true)
          }
      });
  };

  resizeFn();
  $(window).resize(resizeFn);
});

随之而来的 HTML 是:

<div id='before-affix'></div><!-- leave this empty -->
<div data-affix-after='#before-affix'>
    Put content to affix here.
</div>

或者

<div data-affix-after='#create'><!-- any ID that doesn't exist -->
    Put content to affix here.
</div>

所需的 CSS 是:

.affix { top: 0px },
.affix-bottom { position: absolute; }

如果要禁用词缀(例如,当右列堆叠时),请使用 CSS:

.affix, .affix-bottom { position: static; }

在适当的媒体查询中。

胃肠道

于 2015-09-04T12:38:11.777 回答
1

我建议您在附加的 div 周围添加包装器 - 以避免带有附加导航栏的“滚动跳转”。Thomas 发布了很好的解决方案,但它不包括词缀后的折叠空间,并且它在我必须使用的 2.x boostrap 版本中不起作用。所以我决定编写完全新的词缀实现。它不需要boostrap,只需要jquery。这是我的第一个 javascript,所以请怜悯 :) 但也许它会对某人有所帮助。没有引导程序的解决方案总是很好

function myaffix() {

var affixoffset = $('.navbar').offset().top

$('#nav-wrapper').height($(".navbar").height());

$(window).scroll(function () {

    if ($(window).scrollTop() <= affixoffset) {
        $('.navbar').removeClass('affix');
    } else {
        $('.navbar').addClass('affix');
    }
});

};

$(document).ready(function () {

   myaffix();

   $(window).on("resize", function () {
       myaffix();
   });

});

你可以在这里找到例子:http: //jsfiddle.net/3ss7fk92/

于 2015-04-16T16:54:33.047 回答
0

Skelly 以上是正确的,没有更好的方法可以做到这一点。“本机”引导的唯一可能解决方案是使用 JavaScript 调用附加附加选项(如上文在https://stackoverflow.com/a/18702972/2546679中所述)。

尤其不可能使用该data-offset属性来实现相同的效果(即使这会更方便,即使在http://getbootstrap.com/2.3.2/javascript.html#affix上的 Affix 文档提出了希望有人可以这样做)。

所以可以写

data-offset='{"top":42}'

但是一个人是不允许写的,例如:

data-offset='{"top":$("#banner").height()}'

原因是数据属性是通过 JQuery .data()API 解析的,它只允许解析纯 JSON 值,请参阅https://api.jquery.com/data/

于 2015-06-14T10:49:04.940 回答
0

Thnx ThomasReggi 的想法。但写起来可能更正确:

$(this).data('bs.affix').options.offset.top = $(this).offset().top

对于像我这样也需要类似地写的底部值的人。

顺便说一句,我也认为将它包装在基于 setTimeout 的装饰器中(有点像去抖动)。

于 2015-09-20T21:59:22.333 回答
0

早些时候我遇到了很多麻烦,由于某种原因,我无法获得其他人建议的任何解决方案。我对 Bootstrap 和 JQuery 比较陌生,所以我可能正在做一些我没有抓住的奇怪的事情。无论如何,我找到了一个非常有效的解决方案,尽管严格来说它并没有像 Bootstrap 那样使用词缀功能。我保持我的#thisElement.affix {top: desiredFixedPosition;}CSS 完好无损,但去掉了#thisElement 的 HTML 标记中的data-spy和属性。data-offset-top然后我在 JQuery 中对其进行了硬编码:

var newAffix = function() {
    if($("otherElementsAboveThisElement").height() <= $(window).scrollTop()) {
        $("#thisElement").addClass("affix");
    } else {
        $("#thisElement").removeClass("affix");
    }
}

$(document).ready(function() {
    $(window).resize(newAffix);
    $(window).scroll(newAffix);
}

据我测试,无论您调整页面大小或滚动多少,它都有效,如果您对在$(document).ready()函数中调用它的方式有创意,您甚至可以让菜单在高度动画期间保持在正确的位置。如前所述,这在技术上并不是一个完全“Bootstrap 批准”的解决方案,但它可以很好地集成到 Bootstrap 站点中,它应该适用于某些人:)

于 2017-10-18T03:46:16.007 回答