如何获取Bootstrap 3附加方法的动态数据偏移值

时间:2013-09-09 16:03:10

标签: jquery css twitter-bootstrap twitter-bootstrap-3 affix

我想使用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的方式来做这件事,但我确定。

6 个答案:

答案 0 :(得分:44)

您可以使用jQuery将动态内容高度设置为navbar以上。例如:

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

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

在某些情况下,还必须计算offset.bottom以确定何时“取消附加”该元素。 Here's an example of affix-bottom

答案 1 :(得分: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
  })
})

我也在code review发布了此内容。

不要忘记将data-smart-affix属性添加到词缀

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

答案 2 :(得分:3)

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

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

$('[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; }

在适当的媒体查询中。

GI

答案 3 :(得分:1)

我建议你在附加的div周围添加包装 - 以避免&#34;滚动跳转&#34;附加导航栏。托马斯发布了一个很好的解决方案,但是在贴上后它并没有包含复制空间,并且它不能用于我必须使用的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/

答案 4 :(得分:0)

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

特别是可以使用data-offset属性来达到相同的效果(即使这样会更方便,即使是{{3}的文章希望人们可以这样做。)

所以可以写

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

但有一个允许写,例如:

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

原因是数据属性是通过JQuery .data() API解析的,它只允许解析纯JSON值,请参阅http://getbootstrap.com/2.3.2/javascript.html#affix

答案 5 :(得分:0)

我之前遇到了很多麻烦,由于某种原因,我无法得到其他人建议的任何解决方案。我对Bootstrap和JQuery比较陌生,所以我可能会做一些我不喜欢的事情。无论如何,我找到了一个非常有效的解决方案,尽管严格来说并没有像Bootstrap那样使用词缀功能。我保持#thisElement.affix {top: desiredFixedPosition;} CSS完好无损,但摆脱了#thisElement的HTML标记中的data-spydata-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站点中,它应该适用于某些人:)