如何获取 Bootstrap 3 附加方法的动态数据偏移值
Posted
技术标签:
【中文标题】如何获取 Bootstrap 3 附加方法的动态数据偏移值【英文标题】:How to get dynamic data-offset values for Bootstrap 3 affix method 【发布时间】:2013-09-13 04:28:45 【问题描述】:我想使用 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。如果上面的内容是 200 像素高,这可以正常工作,但上面的内容是动态的,因此此导航栏上方的高度并不总是相同。如何使data-offset-top
的值动态化?
我猜我将不得不使用 javascript 的方式来做这件事,但我不确定。
【问题讨论】:
我需要一种方法来重新计算页面调整大小的值,并添加一个空格保持器,以便粘贴运行顺利,例如贴上内容时不跳页。解决方案 -> ***.com/a/47429990/996010 【参考方案1】:您可以使用 jQuery 获取高于 navbar
的动态内容高度。例如:
$('#nav').affix(
offset:
top: $('header').height()
);
工作演示:http://bootply.com/69848
在某些情况下,还必须计算 offset.bottom 以确定何时“取消附加”元素。 Here's an example of affix-bottom
【讨论】:
使用 .outerHeight() 而不是 .height() 来包含边框和内边距【参考方案2】:我对这种工作方式感到非常沮丧,每次进行一些自定义计算并在所需词缀上方的元素高度上建立偏移量。
这是最好的词缀。
普通的 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
。)
【讨论】:
你是我的英雄!谢谢人 .. PS 给其他人:使用此代码时,不要忘记将“data-smart-affix”属性添加到您的 affix 元素。 ;) 最佳答案!做得好。这帮助我解决了我的问题 你的代码有bug,请使用"$(this).data('bs.affix').options.offset.top" 而不是"$(this).data(' bs.affix').options.offset"。我也可以建议使用 [data-offset-top-dynamic 而不是 [data-smart-affix]【参考方案3】:我建议您在附加的 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/
【讨论】:
【参考方案4】:上面的 Skelly 是正确的,没有更好的方法可以做到这一点。 “本机”引导的唯一可能解决方案是通过 JavaScript 调用附加附加选项(如上面在 https://***.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 解析的,该 API 只允许解析纯 JSON 值,参见 https://api.jquery.com/data/。
【讨论】:
你的答案不是动态的,只是静态的。 是的 - 这不是一个独立的答案,而是 Skelly 答案的附录(我不允许发表评论)。我只是想澄清一下,在页面上不使用自定义 JavaScript 来表达动态词缀计算是没有意义的——我已经尝试了几个小时——包括调试引导程序和 JQuery 例程。【参考方案5】: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;
在适当的媒体查询中。
GI
【讨论】:
【参考方案6】:Thnx ThomasReggi 的想法。但写起来可能更正确:
$(this).data('bs.affix').options.offset.top = $(this).offset().top
对于像我这样也需要一个类似的底值的人。
顺便说一句,我也认为将它包装在基于 setTimeout 的装饰器中(有点像 debounce)。
【讨论】:
【参考方案7】:我之前遇到了很多麻烦,由于某种原因,我无法获得其他人建议的任何解决方案。我对 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 站点中,它应该适用于某些人:)
【讨论】:
以上是关于如何获取 Bootstrap 3 附加方法的动态数据偏移值的主要内容,如果未能解决你的问题,请参考以下文章
javascript 方法执行两次 - bootstrap-slider