如何在Bootstrap中设置ScrollSpy的偏移量?


98

我有一个网站,导航栏固定在顶部,主要内容区域下面是3个div。

我正在尝试使用bootstrap框架中的scrollspy。

当您滚动经过div时,它可以成功突出显示菜单中的不同标题。

我也有它,所以当您单击菜单时,它将滚动到页面的正确部分。但是,偏移量是不正确的(它没有考虑导航栏,因此我需要偏移40像素左右)

我在Bootstrap页面上看到它提到了偏移选项,但是我不确定如何使用它。

当它说您可以将scrollspy与一起使用时$('#navbar').scrollspy(),我也不是什么意思,我不确定在哪里包括它,所以我没有,而且一切似乎都在起作用(偏移量除外)。

我以为偏移量可能data-offset='10'在body标签上,但是对我没有任何帮助。

我感觉这确实很明显,我只是想念它。有什么帮助吗?

我的代码是

...
<!-- note: the data-offset doesn't do anything for me -->
<body data-spy="scroll" data-offset="20">
<div class="navbar navbar-fixed-top">
<div class="navbar-inner">
    <div class="container">
    <a class="brand" href="#">VIPS</a>
    <ul class="nav">
        <li class="active">
             <a href="#trafficContainer">Traffic</a>
        </li>
        <li class="">
        <a href="#responseContainer">Response Times</a>
        </li>
        <li class="">
        <a href="#cpuContainer">CPU</a>
        </li>
      </ul>
    </div>
</div>
</div>
<div class="container">
<div class="row">
    <div class="span12">
    <div id="trafficContainer" class="graph" style="position: relative;">
    <!-- graph goes here -->
    </div>
    </div>
</div>
<div class="row">
    <div class="span12">
    <div id="responseContainer" class="graph" style="position: relative;">
    <!-- graph goes here -->
    </div>
    </div>
</div>
<div class="row">
    <div class="span12">
    <div id="cpuContainer" class="graph" style="position: relative;">
    <!-- graph goes here -->
    </div>
    </div>
</div>
</div>

...
<script src="assets/js/jquery-1.7.1.min.js"></script>
<script src="assets/js/bootstrap-scrollspy.js"></script>
</body>
</html>

为什么要给一个职位:相对于您的div?也许这就是造成这种情况的原因。您可以使用您的代码创建一个jsfiddle以便我们看到实际情况吗?
periklis'2

Answers:


113

Bootstrap使用偏移量仅解决间谍问题,而不解决滚动问题。这意味着滚动到适当的位置取决于您。

尝试一下,它对我有用:为导航单击添加事件处理程序。

var offset = 80;

$('.navbar li a').click(function(event) {
    event.preventDefault();
    $($(this).attr('href'))[0].scrollIntoView();
    scrollBy(0, -offset);
});

我在这里找到了它:https : //github.com/twitter/bootstrap/issues/3316


3
感谢你的回答。我花了相当长时间才意识到偏移量不会影响滚动。这意味着任何使用固定顶盖的人都需要以这种方式进行手动调整。
Brian Smith'8

8
要适当地更新URL的哈希部分,请添加window.location.hash = $(this).attr('href')到此函数。
史蒂芬·哈里斯

2
谢谢!FWIW,将数据偏移量放在体内也很重要,因为询问者说它什么也没做,但需要进行适当的监视。有一个全面的答案可能会有所帮助。
mrooney 2013年

4
动态胜利:var navOffset = $('#navbar').height();scrollBy(0, -navOffset);
ahnbizcad 2015年

78

正如Tim所暗示的,诀窍是利用填充。所以问题是,您的浏览器始终希望将锚点滚动到窗口的确切顶部。如果将锚点设置为文本的实际开始位置,则菜单栏将阻止该锚点。相反,您要做的是将锚设置为容器<section><div>标签的ID,导航/导航栏将自动使用该ID。然后,你必须设置你padding-top的容器偏移量你想要的,而margin-top对容器的相反padding-top。现在,您的容器块和锚点从页面的确切顶部开始,但是其中的内容直到菜单栏下方才开始。

如果您使用常规锚点,则可以通过在容器中使用负的margin-top来完成相同的操作,但是不使用填充。然后,您将常规<a target="...">锚点作为容器的第一个孩子。然后使用相反但相等的第二个子元素设置样式margin-top,但使用选择器.container:first-child +

所有这些都假定您的<body>标签已经设置了页边距,该页边距是在标头下方开始的(这是规范)(否则页面将立即显示带有被遮挡的文本)。

这是一个实际的例子。您可以通过在网址末尾添加#the-elements-id来链接页面上所有具有ID的内容。如果您将所有h标签和dt标签都设为具有可链接ID的dt标签(就像github一样),使用某种脚本向其左侧插入一个小链接;在CSS中添加以下内容将为您解决nav-bar偏移:

body {
    margin-top: 40px;/* make room for the nav bar */
}

/* make room for the nav bar */
h1[id],
h2[id],
h3[id],
h4[id],
h5[id],
h6[id],
dt[id]{
    padding-top: 60px;
    margin-top: -40px;
}

9
喜欢填充顶部,负边距底部(在同一元素上)的组合。然后更容易弄乱js。
Eystein

看起来是最好的答案,但我有点迷茫。一个例子的任何机会。
eddyparkinson 2014年

@eddyparkinson,您现在猜出来了:例如,当您的ID位于引导程序的行上时:.row [id] {padding-top:60px; 上边距:-40px; }将其放在您的less文件中:.row [id] {padding-top:60px; 上边距:-40px; }
Klaaz 2014年

引导程序的默认偏移量参数不应该用于此吗?它似乎很容易被包含在内,而不必借助这种变通方法。
ahnbizcad

这样可以有效地在您定位的div上添加额外的空间吗?如果您不想要那怎么办?看不见的额外间距将是理想的。
ahnbizcad

10

您可以使用以下方法动态更改scrollspy的偏移量(假设您在监视身上):

offsetValue = 40;
$('body').data().scrollspy.options.offset = offsetValue;
// force scrollspy to recalculate the offsets to your targets
$('body').data().scrollspy.process();

如果您需要动态更改偏移值,这也可以使用。(我喜欢在下一节位于窗口的大约一半时切换到滚动条,因此在调整窗口大小时需要更改偏移量。)


2
谢谢-只需对Bootstrap 3.0 $('body')。data()['bs.scrollspy']。options.offset = newOffset;进行一些调整即可很好地工作。//设置新的偏移量$('body')。data()['bs.scrollspy']。process(); //强制scrollspy重新计算目标的偏移量$('body')。scrollspy('refresh'); //刷新滚动条。
山姆

我发现这种方法很好,但是如果由于菜单高度不同,我想使用它来设置从开始的偏移量,则$('body')。data()。scrollspy.options.offset(或3.0版的变体)尚未设置。我缺少关于scrollspy的异步信息吗?
ness-EE 2014年

从Bootstrap 3.1.1开始,应该为$('body').data()['bs.scrollspy'].options.offset。使用window.scrollBy(X,Y)
Meredith

8

如果您希望偏移量为10,则可以将其放在脑海中:

<script>
  $('#navbar').scrollspy({
    offset: 10
  });
</script>

您的身体标签如下所示:

<body data-spy="scroll">

6
那不会抵消内容,而是抵消导航。
markus

这将用于突出显示正确的导航元素,而不是单击导致的位置(这是原始海报问题)。话虽如此,这就是我想要的!谢谢!
valin077

6

引导问题#3316开始

[this]仅用于修改滚动计算-我们不会移动实际的锚点

因此,设置offset仅会影响scrollspy认为页面已滚动到的位置。它不影响滚动,当你点击一个锚标记。

使用固定的导航栏意味着浏览器滚动到错误的位置。您可以使用JavaScript修复此问题:

var navOffset = $('.navbar').height();

$('.navbar li a').click(function(event) {
    var href = $(this).attr('href');

    // Don't let the browser scroll, but still update the current address
    // in the browser.
    event.preventDefault();
    window.location.hash = href;

    // Explicitly scroll to where the browser thinks the element
    // is, but apply the offset.
    $(href)[0].scrollIntoView();
    window.scrollBy(0, -navOffset);
});

但是,为了确保scrollspy突出显示正确的当前元素,您仍然需要设置偏移量:

<body class="container" data-spy="scroll" data-target=".navbar" data-offset="70">

这是有关JSFiddle的完整演示


另外,您也可以按照CSS技巧的建议将其填充到锚标签上。

a[id]:before { 
  display: block; 
  content: " ";
  // Use the browser inspector to find out the correct value here.
  margin-top: -285px; 
  height: 285px; 
  visibility: hidden; 
}

1

我认为offset可能会对本节的底部位置有所帮助。

我通过添加来解决了与您相同的问题

  padding-top: 60px;

在bootstrap.css中的声明部分中

希望有帮助!


什么是“部分声明”?您将该代码放在哪里?
ahnbizcad

1

.vspace在每个h1元素之前添加了40px-height 元素来固定锚点。

<div class="vspace" id="gherkin"></div>
<div class="page-header">
  <h1>Gherkin</h1>
</div>

在CSS中:

.vspace { height: 40px;}

它的工作非常好,而且空间不会阻塞。


1

Bootstrap 4(2019更新)

实施:固定Nav,Scrollspy和平滑滚动

这是来自@ wilfred-hughes的解决方案,它通过使用CSS':before'在每个section标记之前添加未显示的块,从而完全解决了Bootstrap Fixed Navbar的重叠问题。优势:您最终不会在各节之间留下不必要的填充。例如,第3部分可以垂直于第2部分垂直放置,并且仍会滚动到第3部分顶部的确切正确位置。

旁注:在script标签中设置scrollspy偏移不会导致任何事情发生($('#navbar')。scrollspy({offset:105});),并且尝试在动画块中调整偏移仍会导致后对齐错误动画。

index.html

<section id="section1" class="my-5">
...
<section id="section2" class="my-5">
...
<section id="section3" class="my-5">
...

稍后在index.html中...

 <script>
      // Init Scrollspy
      $('body').scrollspy({ target: '#main-nav' });

      // Smooth Scrolling
      $('#main-nav a').on('click', function(event) {
        if (this.hash !== '') {
          event.preventDefault();

          const hash = this.hash;

          $('html, body').animate(
            {
              scrollTop: $(hash).offset().top
            },
            800,
            function() {
              window.location.hash = hash;
            }
          );
        }
      });
    </script>

style.css:

// Solution to Fixed NavBar overlapping content of the section.  Apply to each navigable section.
// adjust the px values to your navbar height
// Source: https://github.com/twbs/bootstrap/issues/1768
#section1::before,
#section2::before,
#section3::before {
  display: block;
  content: ' ';
  margin-top: -105px;
  height: 105px;
  visibility: hidden;
}

body {
  padding-top: 105px;
}

信用:上面的@ wilfred-hughes和来自用户@mnot的原始来源位于https://github.com/twbs/bootstrap/issues/1768


1
谢谢!嗯,我已经为此奋斗了一个小时,哈哈!
Nexus

0

我对acjohnson55和Kurt UXD的解决方案有疑问。两者都可以单击散列链接,但是scrollspy偏移量仍然不正确。

我想出了以下解决方案:

<div class="anchor-outer">
  <div id="anchor">
    <div class="anchor-inner">
      <!-- your content -->
    </div>
  </div>
</div>

以及相应的CSS:

body {
  padding-top:40px;
}

.anchor-outer {
  margin-top:-40px;
}

.anchor-inner {
  padding-top:40px;
}

@media (max-width: 979px) {
  body {
    padding-top:0px;
  }

  .anchor-outer {
    margin-top:0px;
  }

  .anchor-inner {
    padding-top:0px;
  }
}

@media (max-width: 767px) {
  body {
    padding-top:0px;
  }

  .anchor-outer {
    margin-top:0px;
  }

  .anchor-inner {
    padding-top:0px;
  }
}

您将需要用导航栏的高度和锚点的ID替换40px的填充/边距。

在此设置中,我什至可以观察到为data-offset属性设置值的效果。如果找到较大的数据偏移值(大约100-200),则会导致更预期的行为(如果标题位于屏幕中间,则将发生scrollspy-“ switch”)。

我还发现,scrollspy对未封闭的div标签(非常明显)之类的错误非常敏感,因此http://validator.w3.org/check是我的朋友。

在我看来,scrollspy最适合带有锚点ID的整个部分,因为常规的锚点元素在向后滚动时不会产生预期的效果(scrollspy-“ switch”最终会在您击中锚点元素时发生,例如您的航向,但到那时,您已经在用户希望属于相应标题的内容上滚动了。


0

如果您通过Google偶然发现了这个问题(就像我一样),并且仍在寻找一种动态更改scrollspy偏移量的方法。我现在将链接链接到对我有用的解决方案。

看一下我在另一个主题中发表的这篇文章。其中包含有关如何以编程方式更改偏移值以及如何对更改进行动态响应(例如,导航栏的大小发生变化)的摘要。

您无需修改​​CSS修复程序,而可以根据某些事件设置当前所需的偏移量。


-1

您也可以打开bootstap-offset.js和修改

$.fn.scrollspy.defaults = {
  offset: 10
}

那里。


1
scrollspy偏移量不会偏移内容,而是会偏移导航。
markus

-1

刚刚设置:

data-offset="200"

data-offset默认情况下为“ 50”,相当于10px,因此只需增加即可data-offset解决问题。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.