BootstrapでScrollSpyのオフセットを設定するにはどうすればよいですか?


98

ナビゲーションバーを上部に固定し、メインコンテンツ領域に3つのdivを配置したサイトがあります。

ブートストラップフレームワークからscrollspyを使用しようとしています。

divを超えてスクロールすると、メニューのさまざまな見出しが正常に強調表示されます。

また、メニューをクリックすると、ページの正しい部分までスクロールします。ただし、オフセットは正しくありません(ナビゲーションバーは考慮されていないため、約40ピクセルオフセットする必要があります)

私は上を参照ブートストラップ・ページにはオフセットオプションを言及しかし、私はそれを使用するかどうかはわかりません。

また$('#navbar').scrollspy()、で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を作成して、実際の動作を確認できますか?
ペリクリス

回答:


113

ブートストラップはオフセットを使用して、スパイではなくスクロールのみを解決します。つまり、適切な場所にスクロールするのはあなた次第です。

これを試してみてください、それは私にとってはうまくいきます:ナビゲーションクリックのイベントハンドラーを追加します。

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
答えてくれてありがとう。オフセットがスクロールに影響を与えないことを理解するのにかなり時間がかかりました。つまり、固定トップを使用している場合は、この方法で手動で調整する必要があります。
ブライアンスミス

8
URLのハッシュセクションを適切に更新するには、window.location.hash = $(this).attr('href')この関数に追加します。
スティーブンM.ハリス

2
ありがとう!FWIW、質問者が何もしないと言っているように、データオフセットを本文に入れることも重要ですが、適切なスパイには必要です。包括的な答えがあると役立つかもしれません。
mrooney 2013年

4
動的な勝利:var navOffset = $('#navbar').height();andscrollBy(0, -navOffset);
ahnbizcad 2015年

78

ティムが言及したように、トリックはパディングを利用することです。したがって、問題は、ブラウザが常にアンカーをウィンドウの最上部にスクロールすることを望んでいることです。テキストを実際に開始する場所にアンカーを設定すると、メニューバーによって隠されます。代わりに、コンテナー<section>または<div>タグのIDにアンカーを設定します。これは、nav / navbarが自動的に使用します。次にpadding-top、コンテナのを必要なオフセットに設定margin-topし、コンテナのをの反対に設定する必要がありpadding-topます。これで、コンテナーのブロックとアンカーはページの一番上から始まりますが、内部のコンテンツはメニューバーの下まで始まりません。

通常のアンカーを使用している場合は、上記のようにコンテナで負のmargin-topを使用し、パディングを使用しないことで同じことを実現できます。次に<a target="...">、コンテナの最初の子として通常のアンカーを配置します。次に、2番目の子要素のスタイルを反対ですが等しいものmargin-topにしますが、セレクターを使用し.container:first-child +ます。

これはすべて、<body>タグのマージンがヘッダーの下から始まるように既に設定されていることを前提としています(それ以外の場合、ページはバットのすぐ近くに隠れたテキストでレンダリングされます)。

これが動作している例です。URLの末尾に#the-elements-idを追加することで、IDを含むページ上のすべてのものにリンクできます。すべてのhタグとdtタグをidでリンク可能にすると(githubのように)、リンクの左側に小さなリンクを挿入するスクリプトのようなものを使用できます。CSSに以下を追加すると、ナビゲーションバーのオフセットが処理されます。

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をいじるのが簡単になります。
アイスタイン

最良の答えのように見えますが、私は少し迷っています。例のチャンス。
エディパーキンソン2014

@eddyparkinson、あなたが今それを理解したと思います:例、あなたのIDがブートストラップの行にあるとき:.row [id] {padding-top:60px; margin-top:-40px; }これをlessファイルに入れます:.row [id] {padding-top:60px; margin-top:-40px; }
Klaaz 2014年

ブートストラップのデフォルトのオフセットパラメータは、このためのものではありませんか?含めるのは明らかなことのようで、このような回避策に頼る必要はありません。
ahnbizcad 2015年

これにより、対象となるdivにスペースが効果的に追加されますか?それを望まない場合はどうしますか?目に見えない余分な間隔が理想的です。
ahnbizcad 2015年

10

あなたはこれでその場でscrollspyのオフセットを変更できます(あなたが体をスパイしていると仮定します):

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

これは、オフセット値を動的に変更する必要がある場合にも機能します。(私は次のセクションがウィンドウの半分ほど上にあるときにscrollspyが切り替わるのが好きなので、ウィンドウのサイズ変更中にオフセットを変更する必要があります。)


2
これをありがとう-Bootstrap 3.0の少しの調整でうまく動作します$( 'body')。data()['bs.scrollspy']。options.offset = newOffset; //新しいオフセットを設定します$( 'body')。data()['bs.scrollspy']。process(); // scrollspyにターゲットへのオフセットを再計算させる$( 'body')。scrollspy( 'refresh'); // scrollspyを更新します。
サム・

この方法は良いことがわかりましたが、メニューの高さが異なるため$( 'body')。data()。scrollspy.options.offset(またはバージョン3.0のバリアントはまだ設定されていません。scrollspyについて非同期の何かがありますか?
ness-EE

Bootstrap 3.1.1以降、これはになるはずです$('body').data()['bs.scrollspy'].options.offset。次を使用してページの読み込み時にscrollspyをトリガーするのに便利ですwindow.scrollBy(X,Y)
Meredith

8

10のオフセットが必要な場合は、これを頭に入れます。

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

bodyタグは次のようになります。

<body data-spy="scroll">

6
これはコンテンツを相殺するのではなく、ナビゲーションを相殺します。
マーカス2013年

これは、クリックがリードする場所(元のポスターの質問)ではなく、正しいナビゲーション要素を強調表示するために機能します。そうは言っても、これは私が探していたものです!ありがとう!
valin077 2015年

6

以下からのブートストラップ問題#3316

[これ]は、スクロール計算を変更することのみを目的としています-実際のアンカークリックはシフトしません

したがって、オフセットの設定は、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

オフセットはセクションの下の位置で何かをするかもしれないと思います。

私は私の問題を修正しました-あなたと同じ-追加することで

  padding-top: 60px;

bootstrap.cssのセクションの宣言

お役に立てば幸いです。


「セクションの宣言」とは何ですかこのコードはどこに配置しますか?
ahnbizcad 2015年

1

.vspaceh1要素の前にアンカーを保持する高さ40pxの要素を追加しました。

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

CSSで:

.vspace { height: 40px;}

それは素晴らしい仕事をしていて、スペースはぎこちないわけではありません。


1

ブートストラップ4(2019更新)

実装:固定ナビゲーション、Scrollspy、およびスムーズスクロール

これは上記の@ wilfred-hughesからの解決策であり、CSS ':: before'を使用して各セクションタグの前に非表示ブロックを追加することにより、ブートストラップ固定ナビゲーションバーとの重複問題を正確に修正します。利点:セクション間に不要なパディングが発生しない。たとえば、セクション3はセクション2に対して垂直に配置できますが、セクション3の上部の正確な正しい位置までスクロールします。

補足:スクリプトタグで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およびhttps://github.com/twbs/bootstrap/issues/1768のユーザー@mnotからの元のソース


ありがとうございました!私はこれに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;
  }
}

40pxのパディング/マージンをnavbarの高さとアンカーのIDで置き換える必要があります。

この設定では、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オフセットはコンテンツをオフセットしません。ナビゲーションをオフセットします。
マーカス2013年

-1

設定するだけ:

data-offset="200"

data-offsetデフォルトは「50」で、これは10pxに相当するので、増やすだけでdata-offset問題は解決します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.