Wie verwende ich das neue Affix-Plugin in Twitter's Bootstrap 2.1.0?

110

Die Bootstrap-Dokumentation zu diesem Thema ist für mich etwas verwirrend. Ich möchte ein ähnliches Verhalten wie in den Dokumenten mit der angehängten Navigationsleiste erzielen: Die Navigationsleiste befindet sich unter einer Absatz- / Seitenüberschrift. Beim Scrollen nach unten sollte zuerst gescrollt werden, bis der obere Rand der Seite erreicht ist, und dann für weitere Bildlaufvorgänge festgehalten werden .

Da jsFiddle nicht mit dem Navbar-Konzept funktioniert, habe ich eine separate Seite zur Verwendung als minimales Beispiel eingerichtet: http://i08fs1.ira.uka.de/~s_drr/navbar.html

Ich benutze dies als meine Navigationsleiste:

<div class="navbar affix-top" data-spy="affix" data-offset-top="50">
    <div class="navbar-inner">
        <div class="container">
            <div class="span12">
                <a class="brand" href="#">My Brand</a> 
                This is my navbar.
             </div>
        </div> <!-- container -->
    </div> <!-- navbar-inner -->
</div> <!-- navbar -->

Ich denke, ich möchte data-offset-topden Wert 0 haben (da der Balken ganz oben "bleiben" sollte, aber bei 50 ist zumindest ein Effekt zu beobachten.

Wenn Sie auch den Javascript-Code einfügen:

     <script>
        $(document).ready (function (){
            $(".navbar").affix ();
        });
     </script>

Jede Hilfe geschätzt.

Dynalon
quelle
Versuchen Sie, affix () in der Hauptnavigationsleiste Ihrer Seite zu verwenden?
Nithin Emmanuel
@NithinEmmanuel ja, siehe das Javascript im Beitrag oder im Beispiel: i08fs1.ira.uka.de/~s_drr/navbar.html
Dynalon
Warum verwenden Sie nicht use .navbar-fixed-topanstelle von affix ()?
Nithin Emmanuel
6
@NithinEmmanuel, weil das nicht das ist, was ich will. .navbar-fixed-topwürde die Navigationsleiste die ganze Zeit nach oben platzieren . Ich möchte einen Seitenkopf ÜBER der Navigationsleiste, und wenn Sie nach unten scrollen (und somit würde die Navigationsleiste weggescrollt), sollte er oben bleiben - dann und nur dann. Bootstrap-Dokumente verwendeten dieselben Mechanismen wie ein Subnav in ihren vorherigen Dokumenten. Leider haben sie diese für die 2.1.0-Dokumente entfernt.
Dynalon
1
Zum einen ist die Verschachtelung Ihres Javascript falsch. )};sollte sein});
Owen

Antworten:

160

Ich hatte ein ähnliches Problem und glaube, ich habe eine verbesserte Lösung gefunden.

Geben Sie nicht data-offset-topin Ihrem HTML an. Geben Sie es stattdessen an, wenn Sie anrufen .affix():

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

Der Vorteil hierbei ist, dass Sie das Layout Ihrer Site ändern können, ohne das data-offset-topAttribut aktualisieren zu müssen . Da hierbei die tatsächlich berechnete Position des Elements verwendet wird, werden auch Inkonsistenzen mit Browsern vermieden, die das Element an einer etwas anderen Position rendern.


Sie müssen das Element weiterhin mit CSS nach oben klemmen. Außerdem musste ich width: 100%das nav-Element setzen, da sich .navElemente position: fixedaus irgendeinem Grund schlecht benehmen:

#nav.affix {
    position: fixed;
    top: 0px;
    width: 100%;
}

Eine letzte Sache: Wenn ein angebrachtes Element fixiert wird, nimmt sein Element keinen Platz mehr auf der Seite ein, was dazu führt, dass die darunter liegenden Elemente "springen". Um diese Hässlichkeit zu verhindern, wickle ich die Navigationsleiste in eine ein, divderen Höhe ich zur Laufzeit so eingestellt habe, dass sie der Navigationsleiste entspricht:

<div id="nav-wrapper">
    <div id="nav" class="navbar">
        <!-- ... -->
    </div>
</div>

.

$('#nav-wrapper').height($("#nav").height());

Hier ist die obligatorische jsFiddle, um sie in Aktion zu sehen .

namuol
quelle
6
Toller Tipp, um den "Sprung" zu entfernen - völlig übersehen die Tatsache, dass dieses Element entfernt wird und dachte, mein Problem sei im affix / js-Teil meines Codes enthalten.
Thomas
1
Diese Antwort ist die beste! Alles funktioniert wie es sollte. Der 'Sprung'-Teil fehlte in den meisten Tutorials, die ich gefunden habe. Vielen Dank!
Ricardo Otero
1
Eine wichtige Korrektur: Verwenden Sie in Ihrem ersten Abfragecode in Ihrem jquery-Code offset () anstelle von position (). Erläuterung: Die Funktion position () gibt Ihnen den Versatz innerhalb des übergeordneten Elements an, aber offset () ist die Position innerhalb des Dokuments, die Sie tatsächlich möchten (ja, die Namen sind nicht intuitiv). Ihr Code würde also nicht funktionieren, wenn sich Ihr Affix-Element in einem anderen Element befindet. Sie sollten auch nur den Wert "top" wie folgt übergeben: $ ("# nav"). Affix ({offset: {top: $ ('# nav'). Offset (). Top. Und er sollte sich in einem Ready befinden () Block, damit Sie wissen, dass das Seitenlayout vollständig ist.
oder
Danke @orrd - Aktualisiere meine Antwort und Geige!
Namuol
Nett! Funktioniert perfekt und ist sehr glatt. Übrigens suche ich das gleiche Beispiel mit einer klebrigen Fußzeile. Wenn Sie wissen, wie das geht, können Sie die jsFiddle aktualisieren? Vielen Dank!
Jocelyn
76

Ich habe dies gerade zum ersten Mal implementiert und hier ist, was ich gefunden habe.

Der data-offset-topWert ist die Anzahl der Pixel, die Sie scrollen müssen, damit der Fixierungseffekt stattfindet. In Ihrem Fall 50pxwird die Klasse Ihres Elements nach dem Scrollen von .affix-topauf geändert .affix. Sie möchten wahrscheinlich in Ihrem Anwendungsfall data-offset-topungefähr festlegen 130px.

Sobald diese Klassenänderung erfolgt ist, müssen Sie Ihr Element in CSS positionieren, indem Sie die Positionierung für die Klasse festlegen .affix. Bootstrap 2.1 ist bereits so definiert .affix, position: fixed;dass Sie lediglich Ihre eigenen Positionswerte hinzufügen müssen.

Beispiel:

.affix {
    position: fixed; 
    top: 20px; 
    left: 0px;
}
Dave Kiss
quelle
1
Thx, das funktioniert etwas. Ich habe meine Beispielseite darauf aktualisiert. Das Problem ist nun, sobald die Navigationsleiste als CSS-Klasse "angebracht" wird, wird die Navigations-CSS-Klasse verworfen. aber ich denke, das ist nur ein Bug / Shortcomming von Bootstrap. Es wird nicht einfach sein, Änderungen vorzunehmen, ohne es in WENIGER zu tun und den Bootstrap neu zu erstellen.
Dynalon
Es sieht für mich so aus, als .navbarob die Klasse erhalten bleibt - sind Sie sicher?
Dave Kiss
Vielen Dank für diese Antwort, ich habe ewig versucht, dies herauszufinden
Reuben
Siehe meine Antwort für eine leicht verbesserte, allgemeinere Lösung.
Namuol
5

Um genau dieses Problem zu beheben, habe ich das Affix-Plugin so geändert, dass es ein jQuery-Ereignis ausgibt, wenn ein Objekt angebracht oder nicht angehängt wird.

Hier ist die Pull-Anfrage: https://github.com/twitter/bootstrap/pull/4712

Und der Code: https://github.com/corbinu/bootstrap/blob/master/js/bootstrap-affix.js

Führen Sie dann die folgenden Schritte aus, um die Navigationsleiste anzubringen:

<script type="text/javascript">
$(function(){
    $('#navbar').on('affixed', function () {
        $('#navbar').addClass('navbar-fixed-top')
    });

    $('#navbar').on('unaffixed', function () {
        $('#navbar').removeClass('navbar-fixed-top')
    });
});
</script>
Corbin U.
quelle
3

Sie müssen .affix()aus Ihrem Skript entfernen .

Bootstrap bietet die Möglichkeit, Dinge data-attributesmeistens entweder über oder direkt über JavaScript zu erledigen .

Patrick Laughlin
quelle
2

Ich habe dies aus dem Quellcode des Twitterbootstraps und es funktioniert ziemlich gut:

HTML:

<div class="row">
    <div class="span3 bs-docs-sidebar">
        <ul id="navbar" class="nav nav-list bs-docs-sidenav">
            ...
        </ul>
    </div>
</div>

CSS:

.bs-docs-sidenav {
    max-height: 340px;
    overflow-y: scroll;
}

.affix {
    position: fixed;
    top: 50px;
    width: 240px;
}

JS:

$(document).ready(function(){
    var $window = $(window);
    setTimeout(function () {
        $('.bs-docs-sidenav').affix({
            offset: {
                top: function (){
                    return $window.width() <= 980 ? 290 : 210
                }
            }
        })
    }, 100);
});
Jesus Rodriguez
quelle
1

Sie müssen nur das Skript entfernen. Hier ist mein Beispiel:

<!DOCTYPE html>
<html>

<head>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.8.0.min.js"></script>
<script type="text/javascript" src="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.1.0/js/bootstrap.min.js"></script>

  <style>
  #content {
    width: 800px;
    height: 2000px;
    background: #f5f5f5;
    margin: 0 auto;
  }
  .menu {
    background: #ccc;
    width: 200px;
    height: 400px;
    float: left;
  }
  .affix {
    position: fixed;
    top: 20px;
    left: auto;
    right: auto;
  }
  </style>

</head>
<body>
    <div id="content">
        <div style="height: 200px"></div>

        <div class="affix-top" data-spy="affix" data-offset-top="180">
            <div class="menu">AFFIX BAR</div>
        </div>
    </div>
</body>
</html>
Beckovsky
quelle
1

Vielen Dank an namuol und Dave Kiss für die Lösung. In meinem Fall hatte ich ein kleines Problem mit der Höhe und Breite der Navigationsleiste, als ich Afflix- und Collapse-Plugins zusammen verwendete. Das Problem mit der Breite kann leicht gelöst werden, indem es vom übergeordneten Element (in meinem Fall Container) geerbt wird. Ich könnte es auch schaffen, dass es mit ein bisschen Javascript (eigentlich Coffeescript) reibungslos zusammenbricht. Der Trick besteht darin, die Höhe des Wrappers auf autovor dem Umschalten des Zusammenbruchs einzustellen und danach wieder zu korrigieren.

Markup (haml):

#wrapper
  #navbar.navbar
    .navbar-inner
      %a.btn.btn-navbar.btn-collapse
        %span.icon-bar
        %span.icon-bar
        %span.icon-bar

      #menu.nav-collapse
        -# Menu goes here

CSS:

#wrapper {
  width: inherit;
}

#navbar {
  &.affix {
    top: 0;
    width: inherit;
  }
}

Coffeescript:

class Navigation
  @initialize: ->
    @navbar = $('#navbar')
    @menu = $('#menu')
    @wrapper = $('#wrapper')

    @navbar.affix({offset: @navbar.position()})
    @adjustWrapperHeight(@navbar.height())

    @navbar.find('a.btn-collapse').on 'click', () => @collapse()

    @menu.on 'shown', () => @adjustWrapperHeight(@navbar.height())
    @menu.on 'hidden', () => @adjustWrapperHeight(@navbar.height())

  @collapse: ->
    @adjustWrapperHeight("auto")
    @menu.collapse('toggle')

  @adjustWrapperHeight: (height) ->
    @wrapper.css("height", height)

$ ->
  Navigation.initialize()
Voldy
quelle
0

Meine Lösung zum Anbringen der Navigationsleiste:

function affixnolag(){

    $navbar = $('#navbar');
    if($navbar.length < 1)
        return false;

    h_obj = $navbar.height();

    $navbar
        .on('affixed', function(){      
            $navbar.after('<div id="nvfix_tmp" style="height:'+h_obj+'px">');
        })
        .on('unaffixed', function(){
            if($('#nvfix_tmp').length > 0)
                $('#nvfix_tmp').remove();
        });
 }
Florian
quelle
0

Ähnlich wie bei der akzeptierten Antwort können Sie auch Folgendes tun, um alles auf einmal zu erledigen:

$('#nav').affix({
  offset: { top: $('#nav').offset().top }
}).wrap(function() {
  return $('<div></div>', {
    height: $(this).outerHeight()
  });
});​

Dadurch wird nicht nur das affixPlugin aufgerufen, sondern auch das angehängte Element in ein div eingeschlossen, das die ursprüngliche Höhe der Navigationsleiste beibehält.

Adrian
quelle