Como usar o novo plugin afixo no bootstrap 2.1.0 do twitter?

110

A documentação de bootstrap sobre esse tópico é um pouco confusa para mim. Desejo obter um comportamento semelhante ao dos documentos com a barra de navegação afixada: a barra de navegação está abaixo de um título de parágrafo / página e, ao rolar para baixo, deve primeiro rolar até chegar ao topo da página e, em seguida, ficar fixada para mais rolagens .

Como jsFiddle não funciona com o conceito de navbar, configurei uma página separada para uso como um exemplo mínimo: http://i08fs1.ira.uka.de/~s_drr/navbar.html

Eu uso isso como minha barra de navegação:

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

Eu acho que gostaria data-offset-topde ter o valor 0 (uma vez que a barra deve "grudar" no topo ", mas com 50 há pelo menos algum efeito assistível.

Se também colocar o código javascript no lugar:

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

Qualquer ajuda apreciada.

Dynalon
fonte
você está tentando usar affix () na barra de navegação principal de sua página?
Nithin Emmanuel de
@NithinEmmanuel sim, veja o javascript no post ou no exemplo: i08fs1.ira.uka.de/~s_drr/navbar.html
Dynalon
por que você não usa use em .navbar-fixed-topvez de affix ()?
Nithin Emmanuel
6
@NithinEmmanuel porque não é isso que eu quero. .navbar-fixed-topcolocaria a barra de navegação no topo o tempo todo . Eu quero um cabeçalho de página ACIMA da barra de navegação e, ao rolar para baixo (e, portanto, a barra de navegação apostaria rolando para longe), ele deve ficar no topo - então e somente então. Os documentos do Bootstrap usavam os mesmos mecanismos que um subnav em seus documentos anteriores, infelizmente eles o removeram para os documentos 2.1.0.
Dynalon de
1
Por um lado, o aninhamento do seu Javascript está incorreto. )};deveria ser});
Owen

Respostas:

160

Eu estava tendo um problema semelhante e acredito que encontrei uma solução melhorada.

Não se preocupe data-offset-topem especificar em seu HTML. Em vez disso, especifique-o ao chamar .affix():

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

A vantagem aqui é que você pode alterar o layout do seu site sem precisar atualizar o data-offset-topatributo. Como isso usa a posição real computada do elemento, também evita inconsistências com navegadores que exibem o elemento em uma posição ligeiramente diferente.


Você ainda precisará prender o elemento na parte superior com CSS. Além disso, tive que definir width: 100%o elemento nav, já que os .navelementos com position: fixedmau comportamento por algum motivo:

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

Uma última coisa: quando um elemento afixado se torna fixo, seu elemento não ocupa mais espaço na página, fazendo com que os elementos abaixo dele "saltem". Para evitar essa feiura, envolvo o navbar em um divcuja altura eu defini para ser igual ao navbar em tempo de execução:

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

.

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

Aqui está o jsFiddle obrigatório para vê-lo em ação .

namuol
fonte
6
Ótima dica para remover o "salto" - esqueci completamente o fato de que esse item foi removido e pensei que meu problema estava contido na parte afixo / js do meu código.
Thomas
1
Essa resposta é a melhor! Tudo funciona como deveria. A parte do 'salto' era a que faltava na maioria dos tutoriais que encontrei. Obrigado!
Ricardo Otero
1
Uma correção importante: use offset () em vez de position () em seu código jquery em seu primeiro trecho de código. Explicação: A função position () fornece o deslocamento dentro do elemento pai, mas offset () é sua posição dentro do documento, que é o que você realmente deseja (sim, os nomes são contra-intuitivos). Portanto, seu código não funcionaria se seu elemento afixo estiver dentro de outro elemento. Você também deve passar apenas o valor "top" como este: $ ("# nav"). Affix ({offset: {top: $ ('# nav'). Offset (). Top. E deve estar dentro de um pronto () bloco para que você saiba que o layout da página está completo.
ou
Obrigado @orrd - Atualizando minha resposta e rabeca!
namuol
Agradável! Funciona perfeitamente e é muito bom. A propósito, estou procurando o mesmo exemplo com um rodapé adesivo. Se você sabe como fazer isso, pode atualizar o jsFiddle? Obrigado!
Jocelyn de
76

Acabei de implementar isso pela primeira vez e aqui está o que descobri.

O data-offset-topvalor é a quantidade de pixels que você deve rolar para que o efeito de fixação ocorra. No seu caso, depois de 50pxrolar a tela, a classe em seu item é alterada de .affix-toppara .affix. Você provavelmente desejaria definir data-offset-toppara aproximadamente 130pxem seu caso de uso.

Depois que essa mudança de classe ocorrer, você deve posicionar seu elemento em css estilizando o posicionamento para a classe .affix. O Bootstrap 2.1 já o define .affix, position: fixed;então tudo que você precisa fazer é adicionar seus próprios valores de posição.

Exemplo:

.affix {
    position: fixed; 
    top: 20px; 
    left: 0px;
}
Dave Kiss
fonte
1
Thx, isso funciona um pouco. Eu atualizei minha página de exemplo para isso. O problema é que, assim que o navbar obtém "afixo" como classe css, a classe css do navbar é descartada. mas eu acho que é apenas um bug / deficiência do bootstrap. Não será fácil mudar sem fazer em LESS e reconstruir o bootstrap.
Dynalon
Parece-me que a .navbarclasse é preservada - tem certeza?
Dave Kiss
Obrigado por esta resposta, passei muito tempo tentando descobrir isso
Reuben,
Veja minha resposta para uma solução um pouco melhorada e mais geral.
namuol
5

Para corrigir esse problema, modifiquei o plugin afixo para emitir um evento jQuery quando um objeto é afixado ou não.

Aqui está a solicitação de pull: https://github.com/twitter/bootstrap/pull/4712

E o código: https://github.com/corbinu/bootstrap/blob/master/js/bootstrap-affix.js

E então faça isso para anexar a barra de navegação:

<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
fonte
3

Você precisa remover .affix()do seu script.

O Bootstrap oferece a opção de realizar coisas via data-attributesou direto JavaScript na maioria das vezes.

Patrick Laughlin
fonte
2

Peguei isso no código-fonte do twitterbootstrap e está funcionando muito bem:

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
fonte
1

Você só precisa remover o script. Aqui está meu exemplo:

<!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
fonte
1

Obrigado a namuol e Dave Kiss pela solução. No meu caso, tive um pequeno problema com a altura e largura da navbar quando usei o aflix e os plug-ins de recolhimento juntos. O problema com a largura pode ser facilmente resolvido herdando-o do elemento pai (recipiente no meu caso). Além disso, consegui fazer com que ele diminuísse suavemente com um pouco de javascript (na verdade, coffeescript). O truque é definir a altura do invólucro para autoantes de ocorrer a alternância de recolhimento e corrigi-lo novamente depois.

Marcação (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
fonte
0

Minha solução para anexar a barra de navegação:

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
fonte
0

Semelhante à resposta aceita, você também pode fazer algo como o seguinte para fazer tudo de uma vez:

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

Isso não apenas invoca o affixplug - in, mas também envolve o elemento afixado em uma div que manterá a altura original da barra de navegação.

Adrian
fonte