web-dev-qa-db-fra.com

Comment créer une barre de navigation collante qui devient fixe après le défilement

J'essaie de créer une barre de navigation qui apparaît au bas de la page visible lors du premier chargement du site, puis lorsque l'utilisateur fait défiler l'écran vers le bas, la barre de navigation défile vers le haut et finit par être fixée au haut. J'utilise Bootstrap, tout comme ce site, mais je n'arrive pas à comprendre comment ce site l'a fait. De l'aide?

Voici le site avec la barre de navigation que j'essaye d'imiter: http://www.blastprocessor.co.uk/

Voici mon code de navigation html et css:

HTML:

<div class="navbar navbar-fixed-top" id="navbar">
    <div class="navbar-inner">
        <div class="container">
            <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
            </a>
            <div class="nav-collapse">
                <ul class="nav nav-pills">
                    <li class="active"><a href="#home">Home</a></li>
                    <li><a href="#service-link">Services</a></li>
                    <li><a href="#contact-link">Contact</a></li>
                </ul><!-- /.nav -->
            </div><!--/.nav-collapse -->
        </div><!-- /.container -->
    </div><!-- /.navbar-inner -->
</div><!-- /.navbar -->

Et voici mon CSS:

.navbar-fixed-top,.navbar-fixed-bottom{position:fixed; -webkit-box-shadow: none; -moz-box-shadow: none; box-shadow: none;}
.navbar .nav > li a{
    color:white; background:rgba(0,0,0,0.2); text-shadow:none; font-size:1.7em; font-family: marvel, serif; padding:.5em 1.3em; margin:1em 2em;
}
.navbar .nav > .active a:hover, .navbar .nav > li a:hover, .navbar .nav > .active a {
    color:white; ; background:#F90; text-shadow:none; font-size:1.7em; font-family: marvel, serif; padding:.5em 1.3em; margin:1em 2em;
}
.navbar .nav > li {padding:2em;}
.navbar.navbar-fixed-top .navbar-inner{background: rgba(255, 255, 255, 0);}
.navbar .nav, .navbar .nav > li {
    float:none;
    display:inline-block;
    *display:inline; /* ie7 fix */
    *zoom:1; /* hasLayout ie7 trigger */
    vertical-align: top;
    padding:0 2em;
}
.navbar-inner {text-align:center;}
.navbar .navbar-inner, .navbar .navbar-inner {border: none; box-shadow: none; filter: none;}
36
Brian

Je cherchais la même chose. J'avais lu que cela était disponible dans Bootstrap 3.0, mais je n'avais aucune chance de le mettre en œuvre. C'est ce que je suis venu avec et cela fonctionne très bien. JQuery et Javascript très simples.

Voici le JSFiddle pour jouer avec ... http://jsfiddle.net/CriddleCraddle/Wj9dD/

La solution est très similaire à d'autres solutions sur le Web et StackOverflow. Si vous ne trouvez pas cela utile, cherchez ce dont vous avez besoin. Bonne chance!

Voici le HTML ...

<div id="banner">
  <h2>put what you want here</h2>
  <p>just adjust javascript size to match this window</p>
</div>

  <nav id='nav_bar'>
    <ul class='nav_links'>
      <li><a href="url">Sign In</a></li>
      <li><a href="url">Blog</a></li>
      <li><a href="url">About</a></li>
    </ul>
  </nav>

<div id='body_div'>
  <p style='margin: 0; padding-top: 50px;'>and more stuff to continue scrolling here</p>
</div>

Voici le CSS ...

html, body {
  height: 4000px;
}

.navbar-fixed {
  top: 0;
  z-index: 100;
  position: fixed;
  width: 100%;
}

#body_div {
  top: 0;
  position: relative;
  height: 200px;
  background-color: green;
}

#banner {
  width: 100%;
  height: 273px;
  background-color: gray;
  overflow: hidden;
}

#nav_bar {
  border: 0;
  background-color: #202020;
  border-radius: 0px;
  margin-bottom: 0;
  height: 30px;
}

//the below css are for the links, not needed for sticky nav
.nav_links {
  margin: 0;
}

.nav_links li {
  display: inline-block;
  margin-top: 4px;
}

.nav_links li a {
  padding: 0 15.5px;
  color: #3498db;
  text-decoration: none;
}

Maintenant, ajoutez simplement le javacript pour ajouter et supprimer la classe de correctif en fonction de la position de défilement.

$(document).ready(function() {
  //change the integers below to match the height of your upper dive, which I called
  //banner.  Just add a 1 to the last number.  console.log($(window).scrollTop())
  //to figure out what the scroll position is when exactly you want to fix the nav
  //bar or div or whatever.  I stuck in the console.log for you.  Just remove when
  //you know the position.
  $(window).scroll(function () { 

    console.log($(window).scrollTop());

    if ($(window).scrollTop() > 550) {
      $('#nav_bar').addClass('navbar-fixed-top');
    }

    if ($(window).scrollTop() < 551) {
      $('#nav_bar').removeClass('navbar-fixed-top');
    }
  });
});
33
SoEzPz

Note (2015): La question et la réponse ci-dessous s’appliquent à l’ancien et obsolète version 2.x de Twitter Bootstrap .

Cette fonctionnalité de création et d'élément "collant" est intégrée au Bootstrap de Twitter et s'appelle Affix . Tout ce que vous avez à faire est d’ajouter:

<div data-spy="affix" data-offset-top="121">
  ... your navbar ...
</div>

autour de votre tag et n'oubliez pas de charger les fichiers JS du Bootstrap comme décrit dans le manuel . L'attribut de données offset-top indique le nombre de pixels de la page (en partant du haut) pour faire défiler le composant de menu. D'habitude c'est juste l'espace en haut de la page.

Remarque: vous devrez prendre soin de l’espace manquant lorsque le menu sera corrigé. Fixer signifie couper le calque de votre page et le coller dans un calque différent qui ne défile pas. Je fais ce qui suit:

<div style="height: 77px;">
  <div data-spy="affix" data-offset-top="121">
    <div style="position: relative; height: 0; width: 100%;">
      <div style="position: absolute; top: 0; left: 0;">
        ... my menu ...
      </div>
    </div>
  </div>
</div>

77px est la hauteur de mon composant apposé.

24
Marcin Skórzewski

// en html

<nav class="navbar navbar-default" id="mainnav">
<nav>

// add in jquery

$(document).ready(function() {
  var navpos = $('#mainnav').offset();
  console.log(navpos.top);
    $(window).bind('scroll', function() {
      if ($(window).scrollTop() > navpos.top) {
       $('#mainnav').addClass('navbar-fixed-top');
       }
       else {
         $('#mainnav').removeClass('navbar-fixed-top');
       }
    });
});

Voici le jsfiddle à jouer: - http://jsfiddle.net/shubhampatwa/46ovg69z/

EDIT: Si vous souhaitez appliquer ce code uniquement aux appareils mobiles, vous pouvez utiliser:

   var newWindowWidth = $(window).width();
    if (newWindowWidth < 481) {
        //Place code inside it...
       }
10
Shubham Patwa

Voici un exemple de Bootstrap 3 qui ne nécessite pas de jQuery supplémentaire .. il utilise le plugin Affix inclus dans Bootstrap 3, mais le balisage de la barre de navigation a changé depuis BS2 ...

<!-- Content Above Nav -->
<header class="masthead">

</header>           


<!-- Begin Navbar -->
<div id="nav">
  <div class="navbar navbar-default navbar-static">
    <div class="container">
      <!-- .btn-navbar is used as the toggle for collapsed navbar content -->
      <a class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
        <span class="glyphicon glyphicon-bar"></span>
        <span class="glyphicon glyphicon-bar"></span>
        <span class="glyphicon glyphicon-bar"></span>
      </a>
      <div class="navbar-collapse collapse">
        <ul class="nav navbar-nav">
          <li class="active"><a href="#">Home</a></li>
          <li class="divider"></li>
          <li><a href="#">Link</a></li>
          <li><a href="#">Link</a></li>
        </ul>
        <ul class="nav pull-right navbar-nav">
          <li>
            ..
          </li>
          <li>
            ..
          </li>
        </ul>
      </div>        
    </div>
  </div><!-- /.navbar -->
</div>

Démo de travail/modèle: http://bootply.com/69848

6
Zim

Cela a bien fonctionné pour moi. N'oubliez pas de placer une croix de remplissage là où se trouvait la barre de navigation, sinon le contenu sautera à chaque fois qu'il est corrigé/corrigé.

function setSkrollr(){
    var objDistance = $navbar.offset().top;
    $(window).scroll(function() {
        var myDistance = $(window).scrollTop();
        if (myDistance > objDistance){
            $navbar.addClass('navbar-fixed-top');
        }
        if (objDistance > myDistance){
            $navbar.removeClass('navbar-fixed-top');
        }
    });
}
5
kaleazy

Utilisez Bootstrap Affix:

/* Note: Try to remove the following lines to see the effect of CSS positioning */
  .affix {
      top: 0;
      width: 100%;
  }

  .affix + .container-fluid {
      padding-top: 70px;
  }
<!DOCTYPE html>
<html>
<head>
  <title>Bootstrap Example</title>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
  
</head>
<body>

<div class="container-fluid" style="background-color:#F44336;color:#fff;height:200px;">
  <h1>Bootstrap Affix Example</h1>
  <h3>Fixed (sticky) navbar on scroll</h3>
  <p>Scroll this page to see how the navbar behaves with data-spy="affix".</p>
  <p>The navbar is attached to the top of the page after you have scrolled a specified amount of pixels.</p>
</div>

<nav class="navbar navbar-inverse" data-spy="affix" data-offset-top="197">
  <ul class="nav navbar-nav">
    <li class="active"><a href="#">Basic Topnav</a></li>
    <li><a href="#">Page 1</a></li>
    <li><a href="#">Page 2</a></li>
    <li><a href="#">Page 3</a></li>
  </ul>
</nav>

<div class="container-fluid" style="height:1000px">
  <h1>Some text to enable scrolling</h1>
  <h1>Some text to enable scrolling</h1>
  <h1>Some text to enable scrolling</h1>
  <h1>Some text to enable scrolling</h1>
  <h1>Some text to enable scrolling</h1>
  <h1>Some text to enable scrolling</h1>
  <h1>Some text to enable scrolling</h1>
  <h1>Some text to enable scrolling</h1>
  <h1>Some text to enable scrolling</h1>
  <h1>Some text to enable scrolling</h1>
  <h1>Some text to enable scrolling</h1>
</div>

</body>
</html>

4
Deepak swain

Vous pouvez utiliser position: sticky

#navbar {
  position: sticky;
  top: 0px;
}

Le #navbar devrait cependant être un enfant direct du corps.

1
Klaasvaak

En réponse à Shubham Patwa: Ainsi, la page est "instable" dès que la classe "navbar-fixed-top" s'applique. C'est parce que le #mainnav est jeté dans et hors du flux DOM du document. Cela peut entraîner un UX laid si la page a une "hauteur critique", sautant entre les positions #mainnav fixes et non fixes.

J'ai modifié le code de cette façon, ce qui semble bien fonctionner (pas parfait, mais parfait):

$(document).ready(function() {
  var navpos = $('#mainnav').offset();
  var navheight = $('#mainnav').outerHeight();

$(window).bind('scroll', function() {
  if ($(window).scrollTop() > navpos.top) {
   $('#mainnav').addClass('navbar-fixed-top');
   $('body').css('marginTop',navheight);
   }
   else {
     $('#mainnav').removeClass('navbar-fixed-top');
     $('body').css('marginTop','0');
   }
});
1
Traumkunst

J'ai trouvé cet extrait de code javascript très utile.

$(document).ready(function()
{
    var navbar = $('#navbar');

    navbar.after('<div id="more-div" style="height: ' + navbar.outerHeight(true) + 'px" class="hidden"></div>');
    var afternavbar = $('#more-div');

    var abovenavbar = $('#above-navbar');

    $(window).on('scroll', function()
    {
        if ($(window).scrollTop() > abovenavbar.height())
        {
            navbar.addClass('navbar-fixed-top');
            afternavbar.removeClass('hidden');
        }
        else
        {
            navbar.removeClass('navbar-fixed-top');
            afternavbar.addClass('hidden');
        }
    });
});
0
Valdrinit