Bootstrap 3.0 scrollspy 响应偏移 [英] Bootstrap 3.0 scrollspy responsive offsets

查看:20
本文介绍了Bootstrap 3.0 scrollspy 响应偏移的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图让 Bootstrap 的 scrollspy 在响应式网站上可靠地工作,在该网站上,顶部导航栏的高度根据媒体/浏览器的宽度而变化.因此,我没有在 data-offset 属性上硬编码偏移量,而是通过 Javascript 初始化动态设置它,如下所示:

$('body').scrollspy({ offset: 70, target: '#nav' });

对于宽布局(即 Bootstrap -lg),它工作正常,但对于较窄的布局,似乎存在累积"偏移.换句话说,它适用于第一部分,但随后需要增加像素来激活以下部分(例如,下一个为 90 像素,第三个为 110 像素,等等).

我尝试直接操作 scrollspy 对象,如本答案所述:如何设置 ScrollSpy 的偏移量在 Bootstrap 中? 但无济于事.

有人可以推荐一种在响应式网站中实现滚动间谍的规范方法,其中偏移量根据媒体宽度而变化吗?

附加信息:

我刚刚分析了两种场景中的 scrollspy 对象,结果表明,当它仅通过 data- 属性初始化时,偏移量列表与通过 JS 初始化时不同.似乎当我通过 JS 初始化它时,偏移数组会在一些 BS 响应调整发生之前填充,因此高度不同. 所有响应式内容都运行后,如何触发 scrollspy 的初始化?BS 完成布局调整后是否有挂钩/回调?JS 是否也参与其中,还是所有响应式的东西都由 CSS 处理?

解决方案

不幸的是,当 $().data(...) 函数第一次被调用.并且 scrollspy 仅在初始化时读取选项一次.scrollspy 的 refresh 功能不会重新加载任何选项.在同一元素上再次调用 $(..).scrollspy(...) 会忽略任何新的数据选项(使用之前初始化的值).

然而,scrollspy确实将选项值存储在键'bs.scrollspy'下的元素数据中.因此,您可以更改该数据键中的 options.offset 字段.

要考虑到动态变化的导航栏高度以及需要更改 scrollspy 偏移值,您可以将以下示例用于可变高度的固定顶部导航栏.

下面做了一些事情.

  • 它通过 javascript 初始化 scrollspy(在 window.load 事件触发后),并以导航栏当前高度的偏移量开始(同时调整主体的 padding-top 值与导航栏高度相同).
  • 监控调整大小事件并调整正文的padding-top,并调整scrollspy offset 以匹配.然后执行 refresh 以重新计算锚点偏移.

HTML

<style type="text/css">/* 防止导航栏在小屏幕上折叠 */#navtop .navbar-nav >li { 浮动:左!重要;}</风格><nav id="navtop" class="navbar-fixed-top" role="navigation"><div class="容器"><ul class="nav nav-pills navbar-nav"><li><a href="#one">One</a></li><li><a href="#two">Two</a></li><li><a href="#three">三</a></li>...更多的导航链接,或影响高度的动态添加的链接...

</nav><section id="one">...</节><section id="两个">...</节><section id="三">...</节>....

JavaScript

$(window).on('load',function(){var $body = $('body'),$navtop = $('#navtop'),偏移 = $navtop.outerHeight();//修复正文填充(以防导航栏大小与填充不同)$body.css('padding-top', offset);//根据导航栏的高度启用具有正确偏移量的 scrollSpy$body.scrollspy({target: '#navtop', offset: offset });//进行调整的函数函数 fixSpy() {//获取元素的 scrollspy 数据的副本var data = $body.data('bs.scrollspy');//如果有数据,让我们摆弄偏移值如果(数据){//获取导航栏的当前高度偏移 = $navtop.outerHeight();//调整 body 的 padding top 以匹配$body.css('padding-top', offset);//更改数据的偏移选项以匹配data.options.offset = 偏移量;//现在把它贴回到元素中$body.data('bs.scrollspy', 数据);//最后刷新scrollspy$body.scrollspy('刷新');}}//现在监视调整大小事件并进行调整var resizeTimer;$(window).resize(function() {clearTimeout(resizeTimer);resizeTimer = setTimeout(fixSpy, 200);});});

就是这样.不漂亮,但绝对有效.我上面的 HTML 可能需要一些调整.

如果您动态地向导航栏添加元素,则需要在插入后调用 fixSpy().或者您可以通过 setInterval(...) 计时器调用 fixSpy() 以一直运行.

I'm trying to get Bootstrap's scrollspy to work reliably on a responsive site on which the top navbar's height changes according to the width of the media/browser. So instead of hardcoding the offset on the data-offset attribute I'm setting it dynamically through Javascript initialization like this:

$('body').scrollspy({ offset: 70, target: '#nav' });

For wide layouts (i.e. Bootstrap -lg) it works fine but for narrower layouts there seems to be an "accumulating" offset in effect. In other words, it works fine for the first section but then takes increasing pixels to activate the following ones (e.g. 90px for the next, 110px for the 3rd, etc.).

I tried manipulating the scrollspy object directly as mentioned in this answer: How do I set the offset for ScrollSpy in Bootstrap? but to no avail.

Can someone recommend a canonical way of implementing scrollspy in a responsive site where the offset varies according to the media width?

Additional Information:

I just analyzed the scrollspy object in both scenarios and it turns out that the list of offsets is different when it's initialized through data- attributes only vs. via JS. It seems like when I initialize it via JS the offsets array gets populated before some of BS responsive adjustments happen and therefore the heights are different. How can I trigger scrollspy's initialization after all the responsive stuff has run? Is there a hook/callback after BS is done adjusting the layout? Is JS even involved or is all the responsive stuff handled by CSS?

解决方案

Unfortunately jQuery pulls in the data-* attributes only once when the $().data(...) function is called the first time. And scrollspy only reads the options once when it is initialised. The refresh function of scrollspy does not reload any of the options. Calling $(..).scrollspy(...) again on the same element ignores any new data options (uses the previously initialized values).

However, scrollspy does store the options values in the elements data under the key 'bs.scrollspy'. So you can alter the options.offset field inside that data key.

To account for a dynamically changing navbar height and the need to alter the scrollspy offset value, you can use the following example for a variable height fixed-top navbar.

The following does a few of things.

  • It initializes scrollspy via javascript (after the window.load event fires), and starts off with an offset of the navbar's current height (also adjusts the body's padding-top value to be the same as the navbar height).
  • Resize events are monitored and the body's padding-top is adjusted, and the scrollspy offset is tweaked to match. Then a refresh is performed to recalculate the anchor offsets.

HTML

<body>
  <style type="text/css">
    /* prevent navbar from collapsing on small screens */
    #navtop .navbar-nav > li { float: left !important; }
  </style>
  <nav id="navtop" class="navbar-fixed-top" role="navigation">
    <div class="container">
      <ul class="nav nav-pills navbar-nav">
        <li><a href="#one">One</a></li>
        <li><a href="#two">Two</a></li>
        <li><a href="#three">Three</a></li>
      ... some more navlinks, or dynamically added links that affect the height ...
      </ul>
    </div>
  </nav>
  <section id="one">
   ...
  </section>
  <section id="two">
   ...
  </section>
  <section id="three">
   ...
  </section>
   ....
</body>

JavaScript

$(window).on('load',function(){
    var $body   = $('body'), 
        $navtop = $('#navtop'),
        offset  = $navtop.outerHeight();

    // fix body padding (in case navbar size is different than the padding)
    $body.css('padding-top', offset);
    // Enable scrollSpy with correct offset based on height of navbar
    $body.scrollspy({target: '#navtop', offset: offset });

    // function to do the tweaking
    function fixSpy() {
        // grab a copy the scrollspy data for the element
        var data = $body.data('bs.scrollspy');
        // if there is data, lets fiddle with the offset value
        if (data) {
            // get the current height of the navbar
            offset = $navtop.outerHeight();
            // adjust the body's padding top to match
            $body.css('padding-top', offset);
            // change the data's offset option to match
            data.options.offset = offset;
            // now stick it back in the element
            $body.data('bs.scrollspy', data);
            // and finally refresh scrollspy
            $body.scrollspy('refresh');
        }
    }

    // Now monitor the resize events and make the tweaks
    var resizeTimer;
    $(window).resize(function() {
        clearTimeout(resizeTimer);
        resizeTimer = setTimeout(fixSpy, 200);
    });
});

And thats it. Not pretty, but it definitely works. My HTML above may need some tweaking.

If you add elements to your navbar dynamically you will need to call fixSpy() after they are inserted. Or you could call fixSpy() via a setInterval(...) timer to run all the time.

这篇关于Bootstrap 3.0 scrollspy 响应偏移的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆