wake-up-neo.com

So erhalten Sie dynamische Datenversatzwerte für die Bootstrap 3-Affixmethode

Ich möchte die Affix-Methode verwenden, die in der Bootstraps-Dokumentation ( http://getbootstrap.com/javascript/#affix ) beschrieben ist. Die Navbar möchte ich jedoch an den Anfang der Seite setzen, nachdem sie gescrollt wurde können unterschiedliche Offset-Werte haben, abhängig vom darüber liegenden Inhalt.

Hier ist ein Beispiel für die 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>

Wie Sie sehen, ist der data-offset-top derzeit auf 200 eingestellt. Dies funktioniert gut, wenn der Inhalt oben 200px hoch ist, der Inhalt oben jedoch dynamisch ist und die Höhe über dieser Navigationsleiste nicht immer gleich ist. Wie kann ich den Wert für data-offset-top dynamisch gestalten?

Ich schätze, ich muss die Javascript-Methode verwenden, aber ich bin mir nicht sicher.

31
bigmike7801

Sie können jQuery verwenden, um die Höhe des dynamischen Inhalts über navbar zu ermitteln. Zum Beispiel:

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

Arbeitsdemo: http://bootply.com/69848

In einigen Fällen muss auch offset.bottom berechnet werden, um zu bestimmen, wann das Element entfernt werden soll. Hier ist ein Beispiel für Affix-Bottom

44
Zim

Ich war absolut frustriert darüber, wie das funktioniert, jedes Mal, wenn ich eine benutzerdefinierte Berechnung durchführte und den Versatz aus den Höhen der Elemente über dem gewünschten Affix aufbaute. 

Hier ist ein Affix vom Feinsten.

Der normale Boostrap-Affix berücksichtigt nicht die natürliche obere Position des Elements, sondern muss manuell als Attribut übergeben werden. Dies kümmert sich darum und trägt dazu bei, dass sich der Versatz bei der Größenänderung des Fensters ändert.

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
  })
})

Ich habe dies auch auf code review gepostet.

Vergessen Sie nicht, das data-smart-affix-Attribut zu Ihrem Affix-Element hinzuzufügen

Probieren Sie diesen Beispielcode aus: https://jsfiddle.net/NabiKAZ/qyrauogw/
(In diesem Beispiel kann die Höhe des roten Abschnitts 100px oder 200px oder 300px in der Differenzbreite des Fensters betragen. Sie müssen also beim Scrollen den Code data-offset-top ändern.)

21
ThomasReggi

Der Daten-Smart-Affix von ThomasReggi funktionierte für mich in einigen Eckfällen nicht (bei der Größenänderung des Dokuments oder bei zu großer Spalte). Es ergab sich jedoch eine einfache Idee: Fügen Sie vor dem angefügten Inhalt ein leeres Element hinzu, und verwenden Sie das, um den Versatz zu erhalten. Funktioniert gut, wenn Sie die Größe ändern.

Dabei habe ich auch die Breite des Elements auf seine natürliche Breite im ursprünglichen übergeordneten Element festgelegt. Hier ist meine Lösung:

$('[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);
});

Der dazugehörige HTML-Code lautet:

<div id='before-affix'></div><!-- leave this empty -->
<div data-affix-after='#before-affix'>
    Put content to affix here.
</div>

oder

<div data-affix-after='#create'><!-- any ID that doesn't exist -->
    Put content to affix here.
</div>

Das erforderliche CSS ist:

.affix { top: 0px },
.affix-bottom { position: absolute; }

Wenn Sie das Anfügen deaktivieren möchten (z. B. wenn die rechte Spalte gestapelt ist), verwenden Sie das CSS:

.affix, .affix-bottom { position: static; }

in der entsprechenden Medienabfrage.

GI

3
gi1242

Ich schlage vor, dass Sie einen Wrapper um ein angehängtes div hinzufügen - um den "Bildlaufsprung" mit der angebrachten Navbar zu vermeiden. Thomas hat eine Nizza-Lösung gepostet, die jedoch nach dem Fixieren keinen eingefügten Raum enthält und in der 2.x-Boostrap-Version, die ich verwenden muss, nicht funktioniert. Also entschied ich mich für eine komplett neue Implementierung von Affix. Es braucht keine Boostrap, nur Jquery. Es ist mein erstes Javascript, also habt bitte Gnade :) aber vielleicht hilft es jemandem. Es ist immer schön, eine Lösung ohne Bootstrap zu haben

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();
   });

});

Ein Beispiel finden Sie hier: http://jsfiddle.net/3ss7fk92/

1
pixelofficer

Ich hatte früher große Probleme damit und aus irgendeinem Grund konnte ich keine der Lösungen finden, die andere Leute vorgeschlagen hatten, um zu arbeiten. Ich bin relativ neu bei Bootstrap und JQuery, also habe ich wahrscheinlich etwas Ungewöhnliches getan, das ich nicht verstanden habe. Trotzdem habe ich eine Lösung gefunden, die wirklich gut funktioniert, obwohl sie die Affix-Funktionalität nicht strikt verwendet, wie es Bootstrap vorsieht. Ich habe mein #thisElement.affix {top: desiredFixedPosition;}-CSS beibehalten, aber die data-spy- und data-offset-top-Attribute aus dem HTML-Tag von # thisElement entfernt. Ich habe dies dann in JQuery hartcodiert:

var newAffix = function() {
    if($("otherElementsAboveThisElement").height() <= $(window).scrollTop()) {
        $("#thisElement").addClass("affix");
    } else {
        $("#thisElement").removeClass("affix");
    }
}

$(document).ready(function() {
    $(window).resize(newAffix);
    $(window).scroll(newAffix);
}

Soweit ich es getestet habe, funktioniert dies unabhängig davon, wie viel Sie die Seite oder den Bildlauf ändern, und wenn Sie kreativ werden, wie Sie es in der $(document).ready()-Funktion aufrufen, könnte das Menü während Höhenanimationen sogar in der richtigen Position bleiben. Wie gesagt, dies ist technisch gesehen keine vollständig "von Bootstrap zugelassene" Lösung, aber sie lässt sich gut genug in eine Bootstrap-Site integrieren, sodass sie für einige funktionieren sollte :)

0
Patrick Menard

Skelly oben ist richtig und es gibt keinen besseren Weg, dies zu tun. Die einzig mögliche Lösung mit "nativem" Bootstrap besteht darin, die Affix-Optionen mit einem JavaScript-Aufruf zu verknüpfen (wie oben in https://stackoverflow.com/a/18702972/2546679 erwähnt).

Es ist insbesondere not möglich, das data-offset-Attribut zu verwenden, um den gleichen Effekt zu erzielen (selbst wenn dies wesentlich bequemer wäre und selbst wenn die Dokumentation für Affix unter http://getbootstrap.com/2.3.2 /javascript.html#affix erhöht die Hoffnung, dass man dies tun könnte).

So kann man schreiben 

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

aber man darf nicht schreiben, z.

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

Der Grund ist, dass die Datenattribute über die JQuery .data()-API analysiert werden, wodurch nur reine JSON-Werte analysiert werden können, siehe https://api.jquery.com/data/ .

0
haui

Danke an ThomasReggi für eine Idee. Kann aber richtiger sein zu schreiben:

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

für diejenigen wie mich, die auch einen untersten Wert brauchten, der analog schreiben würde.

Übrigens denke ich auch, dass ich es in einen Dekorateur einwickle, der auf setTimeout basiert (ähnlich wie Debounce).

0
discodanser