web-dev-qa-db-ja.com

Bootstrap 3 affix methodの動的データオフセット値を取得する方法

Bootstrapsのドキュメント( http://getbootstrap.com/javascript/#affix )で説明されているAffixメソッドを使用したいのですが、その後のページの上部に修正したいnavbarそれまでのスクロールは、その上のコンテンツに応じて異なるオフセット値を持つことができます。

Navbarの例を次に示します。

<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ピクセルの場合、これは正常に機能しますが、上記のコンテンツは動的であるため、このnavbarの上の高さは常に同じではありません。 data-offset-topの値を動的にするにはどうすればよいですか?

私はそれを行うにはjavascriptの方法を使用する必要があると推測していますが、私は確信しています。

32
bigmike7801

JQueryを使用して、navbarより上の動的コンテンツの高さを取得できます。例えば:

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

動作デモ: http://bootply.com/69848

場合によっては、offset.bottomを計算して、要素を「付加解除」するタイミングを決定する必要もあります。 これはaffix-bottomの例です

44
Zim

私はこれがどのように機能するかに不満を感じていました。毎回カスタム計算を行い、目的の接辞上の要素の高さからオフセットを構築するたびに。

これが最良の接辞です。

通常の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_属性をaffix要素に追加することを忘れないでください

このサンプルコードを試してください: https://jsfiddle.net/NabiKAZ/qyrauogw/
(このサンプルでは、​​ウィンドウの差分幅で赤いセクションの高さが100pxまたは200pxまたは300pxになる場合があるため、スクロールするときに_data-offset-top_を差分する必要があります。)

21
ThomasReggi

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

3
gi1242

貼り付けられたdivの周りにラッパーを追加することをお勧めします-貼り付けられたnavbarによる「スクロールジャンプ」を回避するため。トーマスはニースのソリューションを投稿しましたが、接辞の後に折りたたまれたスペースは含まれておらず、使用する必要のある2.xブーストラップバージョンでは動作しません。だから、私は完全に新しい接辞の実装を書くことにしました。 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/

1
pixelofficer

私は以前これで多くの問題を抱えていましたが、何らかの理由で他の人が提案した解決策を得ることができませんでした。私は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サイトで十分に機能するはずです:)

0
Patrick Menard

上記のSkellyが正しいので、これを行うより良い方法はありません。 "native" bootstrapで唯一可能な解決策は、上記の https://stackoverflow.com/a/18702972/2546679で述べたように、接尾辞オプションをJavaScript呼び出しでアタッチすることです。 )。

特に、notを使用して、data-offset属性を使用して同じ効果を得ることができます(これがはるかに便利な場合でも、 http:// getbootstrap。 com/2.3.2/javascript.html#affix は、そうすることができるという希望をもたらします)。

だから、書くことができます

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

しかし、1つはnotの書き込みが許可されています。例:

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

その理由は、純粋なJSON値のみを解析できるJQuery .data() AP​​Iを介してデータ属性が解析されるためです。 https://api.jquery.com/data/ を参照してください。

0
haui

Thnx ThomasReggiのアイデア。しかし、書く方が正しいかもしれません:

$(this).data('bs.affix').options.offset.top = $(this).offset().top

アナロジー的に書くボトム値も必要とする私のような人のために。

ところで、私はsetTimeout(デバウンスのようなもの)に基づいてデコレータでそれをラップすると思います。

0
discodanser