Javascript 如何创建滚动后固定在顶部的粘性导航栏

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14667829/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 17:33:33  来源:igfitidea点击:

How to create a sticky navigation bar that becomes fixed to the top after scrolling

javascripthtmlcsstwitter-bootstrapnav

提问by Brian

I'm attempting to make a nav bar that appears at the bottom of the viewable page when the site is first loaded, then as the user scrolls down, the nav bar scrolls up, and eventually becomes fixed to the top. I'm using Bootstrap, just like this site, but I can't figure out how this site did it. Any help?

我正在尝试制作一个导航栏,该导航栏在网站首次加载时出现在可查看页面的底部,然后当用户向下滚动时,导航栏会向上滚动,并最终固定在顶部。我正在使用 Bootstrap,就像这个网站一样,但我不知道这个网站是怎么做的。有什么帮助吗?

Here's the site with the nav bar I'm trying to emulate: http://www.blastprocessor.co.uk/

这是我试图模仿的带有导航栏的网站:http: //www.blastprocessor.co.uk/

Here's my navigation html and css code:

这是我的导航 html 和 css 代码:

HTML:

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

And here's my CSS:

这是我的 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;}

回答by SoEzPz

I was searching for this very same thing. I had read that this was available in Bootstrap 3.0, but I was having no luck in actually implementing it. This is what I came up with and it works great. Very simple jQuery and Javascript.

我正在寻找同样的东西。我读过这在 Bootstrap 3.0 中可用,但我没有真正实现它。这是我想出来的,效果很好。非常简单的 jQuery 和 Javascript。

Here is the JSFiddle to play around with... http://jsfiddle.net/CriddleCraddle/Wj9dD/

这是 JSFiddle 玩... http://jsfiddle.net/CriddleCraddle/Wj9dD/

The solution is very similar to other solutions on the web and StackOverflow. If you do not find this one useful, search for what you need. Goodluck!

该解决方案与网络和 StackOverflow 上的其他解决方案非常相似。如果您觉得这个没有用,请搜索您需要的内容。祝你好运!

Here is the HTML...

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

Here is the CSS...

这是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;
}

Now, just add the javacript to add and remove the fix class based on the scroll position.

现在,只需添加 javacript 即可根据滚动位置添加和删除修复类。

$(document).ready(function() {
  //change the integers below to match the height of your upper div, 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');
    }
  });
});

回答by Marcin Skórzewski

Note (2015): Both question and the answer below apply to the old, deprecated version 2.x of Twitter Bootstrap.

注意(2015):下面的问题和答案都适用于旧的、已弃用的 Twitter Bootstrap 2.x 版本

This feature of making and element "sticky" is built into the Twitter's Bootstrap and it is called Affix. All you have to do is to add:

这种制作和元素“粘性”的功能内置于 Twitter 的 Bootstrap 中,它被称为Affix。您所要做的就是添加:

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

around your tag and do not forget to load the Bootstrap's JS files as described in the manual. Data attribute offset-toptells how many pixels the page is scrolled (from the top) to fix you menu component. Usually it is just the space to the top of the page.

在你的标签周围,不要忘记按照手册中的描述加载 Bootstrap 的 JS 文件。数据属性offset-top告诉页面滚动(从顶部)多少像素来修复你的菜单组件。通常它只是页面顶部的空间。

Note: You will have to take care of the missing space when the menu will be fixed. Fixing means cutting it off out of your page layer and pasting in different layer that does not scroll. I am doing the following:

注意:当菜单被修复时,您必须处理丢失的空间。修复意味着将其从您的页面层中切除并粘贴到不滚动的不同层中。我正在做以下事情:

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

where 77pxis the height of my affixed component.

77px我的附加组件的高度在哪里。

回答by Shubham Patwa

//in html

//在html中

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

// add in jquery

// 在 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');
       }
    });
});

Here is the jsfiddle to play around : -http://jsfiddle.net/shubhampatwa/46ovg69z/

这是要玩的 jsfiddle: - http://jsfiddle.net/shubhampatwa/46ovg69z/

EDIT: if you want to apply this code only for mobile devices the you can use:

编辑:如果您只想将此代码应用于移动设备,您可以使用:

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

回答by Zim

Bootstrap 4 - Update 2020

Bootstrap 4 - 2020 年更新

The Affix plugin no longer exists in Bootstrap 4, but now most browsers support position:stickywhich can be used to create a sticky after scoll Navbar. Bootstrap 4 includes the sticky-topclass for this...

Bootstrap 4 中不再存在 Affix 插件,但现在大多数浏览器都支持position:sticky它可用于创建 scoll Navbar 后的粘性。Bootstrap 4 包括这个sticky-top类......

https://codeply.com/go/oY2CyNiA7A

https://codeply.com/go/oY2CyNiA7A

Bootstrap 3 - Original Answer

Bootstrap 3 - 原始答案

Here's a Bootstrap 3 example that doesn't require extra jQuery.. it uses the Affixplugin included in Bootstrap 3, but the navbar markup has changed since BS2...

这是一个不需要额外 jQuery 的 Bootstrap 3 示例..它使用AffixBootstrap 3 中包含的插件,但自 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>

Working demo/template: http://bootply.com/69848

工作演示/模板:http: //bootply.com/69848

回答by kaleazy

This worked great for me. Don't forget to put a filler div in there where the navigation bar used to be, or else the content will jump every time it's fixed/unfixed.

这对我很有用。不要忘记在导航栏曾经所在的位置放置一个填充 div,否则每次固定/未固定时内容都会跳转。

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

回答by Deepak swain

Use Bootstrap Affix:

使用 Bootstrap 词缀:

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

回答by mckenna

For Bootstrap 4, a new class was released for this. According to the utilties docs:

对于 Bootstrap 4,为此发布了一个新类。根据实用程序文档

Apply the class sticky-top.

应用类sticky-top。

<div class="sticky-top">...</div>

For further navbar position options, visit here. Also, keep in mind that position: sticky;is not supported in every browser so this may not be the best solution for you if you need to support older browsers.

如需更多导航栏位置选项,请访问此处。此外,请记住,position: sticky;并非每个浏览器都支持它,因此如果您需要支持旧浏览器,这可能不是您的最佳解决方案。

回答by Klaasvaak

You could use position: sticky

你可以用 position: sticky

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

The #navbar should be a direct child of the body though.

不过,#navbar 应该是 body 的直接子级。

回答by Traumkunst

In answer to Shubham Patwa: This way, the page is "jumpy" soon as the class "navbar-fixed-top" applies. That's because the #mainnav is throwen in and out of the document's DOM flow. This can result in an ugly UX if the page has a "critical height", jumping between fixed and un-fixed #mainnav position.

回答 Shubham Patwa:这样,一旦应用“导航栏固定顶部”类,页面就会“跳跃”。那是因为#mainnav 被扔进和扔出文档的 DOM 流。如果页面具有“临界高度”,在固定和未固定的#mainnav 位置之间跳转,这可能会导致丑陋的用户体验。

I altered the code this way, which seems to work fine (not pixel-perfect, but fine):

我以这种方式更改了代码,这似乎工作正常(不是像素完美,但很好):

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

回答by Valdrinium

I have found this simple javascript snippet very useful.

我发现这个简单的 javascript 片段非常有用。

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