在滚动时使元素固定

32

我想让导航栏固定在顶部,当用户滚动到导航栏时,它会保持固定,当用户向上滚动超过导航栏时,它会取消固定。我知道只有通过JavaScript才能实现这个功能。作为JavaScript的初学者,越简单越好。 JSFIDDLE在此处

HTML代码如下:

   <section class="main">
     <div id="wrap">
        <div id="featured">
     <div class="wrap">      
  <div class="textwidget">
    <div class="cup"><img src="#""></div>
<div id="header"></div></div></div></div></div></div></div>
<div class="whiteboard">
         <h1><a href="#">HELLO GUYS</a></h1> </div>
   </div>
          <div class="bg1">
            <h2> WE ARE AN EVENTS MANAGEMENT COMPANY BASED IN LONDON. </h2></div>

CSS如下:

      .main{text-align:center;}

      h1{
          -webkit-font-smoothing: antialiased;
              display:inline-block;
            font: 800 1.313em "proxima-nova",sans-serif; 
            padding: 10px 10px;
            margin: 20px 20px;
            letter-spacing: 8px;
            text-transform: uppercase;
              font-size:3.125em;
              text-align: center; 
              max-width: 606px;
      line-height: 1.45em;
      position: scroll;
          background-color:#e94f78;
          text-decoration: none;
          color:yellow;
          background-image:url;
      }

      h1 a{
        text-decoration: none;
        color:yellow;
                padding-left: 0.15em;
      }

      h2{
          -webkit-font-smoothing: antialiased;
              display:inline-block;
            font: 800 1.313em "proxima-nova",sans-serif; 
            letter-spacing: 8px;
            margin-top: 100px;
            text-transform: uppercase;
              font-size:3.125em;
              text-align: center; 
      line-height: 1.45em;
      position: scroll;
          text-decoration: none;
          color:white;
          z-index: -9999;
      }

      h2 a{
        text-decoration: none;
        color:white;
                padding-left: 0.15em;
      }

      h5{

      position: absolute;
              font-family:sans-serif; 
              font-weight:bold; 
              font-size:40px; 
              text-align: center; 
              float: right;
              background-color:#fff;
              margin-top: -80px;
              margin-left: 280px;
      }

      h5 a{

        text-decoration: none;
        color:red;
      }

      h5 a:hover{

        color:yellow;
      }

      #text1{
          -webkit-font-smoothing: antialiased;
              display:inline-block;
            font: 800 1.313em "proxima-nova",sans-serif; 
            margin: 20px 20px;
            letter-spacing: 8px;
            text-transform: uppercase;
              font-size:3.125em;
              text-align: center; 
              max-width: 606px;
      line-height: 1.45em;
      position: scroll;
          background-color:#E94F78;

      }

      #text1 a{
          color:yellow;
          text-decoration: none;
              padding-left: 0.15em;


      }

      #text1 a:hover{

          text-decoration: none;
          cursor:pointer;
      }

      .whiteboard{
          background-image:url(http://krystalrae.com/img/krystalrae-2012-fall-print-leopard-sketch.jpg);
          background-position: center;
          padding: ;
          background-color: #fff;
          z-index: 1000;
      }

      .bg{
        height:2000px;
        background-color:#ff0;
        background-image:url(http://alwayscreative.net/images/stars-last.jpg);
        position:relative;
        z-index: -9999;

      }
      .bg1{
        background-image:url(http://alwayscreative.net/images/stars-last.jpg);
        z-index: -9999;
        height:1000px;
      }
      /* Header */
      #wrap {
        margin: 0 auto;
        padding: 0;
        width: 100%;
      }

      #featured {
        background: #E94F78 url(http://www.creativityfluid.com/wp-content/themes/creativityfluid/images/img-bubbles-red.png) no-repeat top;
        background-size: 385px 465px;
        color: #fff;
        height: 535px;
        overflow: hidden;
        position: relative;
        z-index: -2;
      }


      #featured .wrap {
        overflow: hidden;
        clear: both;
        padding: 70px 0 30px;
        position: fixed;
        z-index: -1;
        width: 100%;
      }


      #featured .wrap .widget {
        width: 80%;
        max-width: 1040px;
        margin: 0 auto;
      }

      #featured h1,
      #featured h3,
      #featured p {
        color: yellow;
        text-shadow: none;
      }

      #featured h4{
        color:white;
        text-shadow:none;
      }

      #featured h4 {
        margin: 0 0 30px;
      }

      #featured h3 {
        font-family: 'proxima-nova-sc-osf', arial, serif;
        font-weight: 600;
        letter-spacing: 3px;
      }

      #featured h1 {
        margin: 0;
      }

      .textwidget{
        padding: 0;
      }

      .cup{
        margin-top:210px;
        z-index: 999999;
      }

      .container{font-size:14px; margin:0 auto; width:960px}
      .test_content{margin:10px 0;}
      .scroller_anchor{height:0px; margin:0; padding:0;background-image:url()}
      .scroller{background:#FFF;
        background-image:url(http://krystalrae.com/img/krystalrae-2012-fall-print-leopard-sketch.jpg);
       margin:0 0 10px; z-index:100; height:50px; font-size:18px; font-weight:bold; text-align:center; width:960px;}

4
你为什么说你是JAVA的初学者?也许你是指JavaScript?记住,除了它们名字中相同的前缀外,JavaScript与JAVA没有任何关系:P - Xavier_Ex
2
是的,JavaScript之所以被命名为JavaScript,是因为Java取得了巨大的成功(或者说是炒作)。在此之前,它是由发明者Netscape称为LiveScript的(还有人记得吗?)。 - yunzen
你期望这个能在哪些浏览器上运行?这是你问题中最大的变量。 - hharnisc
11个回答

83
你可以通过一些简单的jQuery来实现: http://jsfiddle.net/jpXjH/6/
var elementPosition = $('#navigation').offset();

$(window).scroll(function(){
        if($(window).scrollTop() > elementPosition.top){
              $('#navigation').css('position','fixed').css('top','0');
        } else {
            $('#navigation').css('position','static');
        }    
});

此外,并非所有浏览器都能正确呈现“fixed”CSS。所有现代浏览器都可以,但是旧版浏览器(甚至是Nokia N900上的Opera)可能无法很好地运行。 - Julian H. Lam
1
基本版本:http://jsfiddle.net/Pat712/YY2F8/ - Patrick Borkowicz
更短的滚动回调函数:$('#navigation').css('position', ($(window).scrollTop()>elementPosition.top) ? 'fixed' : 'relative');(并在您的CSS中设置top:0)-- http://jsfiddle.net/mblase75/jpXjH/133/ - Blazemonger
在2015年,使用这个解决方案仍然存在IE的性能问题,你有其他想法吗? - Black Cid

21

我认为使用jQuery或LESS没有必要,对于我来说,JavaScript框架过于复杂。

window.addEventListener('scroll', function (evt) {

  // This value is your scroll distance from the top
  var distance_from_top = document.body.scrollTop;

  // The user has scrolled to the tippy top of the page. Set appropriate style.
  if (distance_from_top === 0) {

  }

  // The user has scrolled down the page.
  if(distance_from_top > 0) {

  }

});

5
但是为了具有广泛的浏览器兼容性,您还必须使用attachEvent。 - yunzen
5
问题并不是关于浏览器兼容性的。我试图让它保持相关性和易于理解。 - Shawn Whinnery
但是你的答案并不完全正确,如果你不使用jQuery的话。因为jQuery的一部分是处理兼容性问题。 - yunzen
12
这个问题不是关于浏览器兼容性的。 - Shawn Whinnery
我并不是说你的答案是错的。但是你可以通过添加一些兼容性代码来大大改进它。 - yunzen

15

针对实现这个方法存在的一些问题,原有的答案没有涉及到:

  1. window的onscroll事件会频繁触发,这意味着你需要使用高效的监听器或者以某种方式延迟该监听器。jQuery 的创始人 John Resig 在这里提到了如何实现延迟机制以及为什么要这样做。我认为,鉴于今天的浏览器和环境,一个高效的监听器也能很好地解决这个问题。这里是 John Resig 建议的模式的实现
  2. CSS 中的position:fixed属性会导致页面滚动后将元素从position:static移动到position: fixed时,页面会出现“跳动”,因为文档“丢失”了该元素的高度。你可以通过将高度添加到scrollTop中,并在文档主体中用另一个对象替换丢失的高度来解决这个问题。你还可以使用该对象来确定粘性项目是否已经移动到position: fixed,并减少恢复position: fixed到原始状态的代码调用。点击这里查看示例
  3. 现在,从性能的角度来看,处理程序真正做的唯一昂贵的事情就是在每次调用时调用scrollTop。由于时间间隔绑定处理程序也有其缺点,我会在这里提出一个论点:重新将事件监听器附加到原始滚动事件上,以使它感觉更加灵敏,而不必太担心性能问题。不过,你需要对你支持的每个浏览器进行测试和分析。点此查看它的运行情况

以下为代码:

JS

/* Initialize sticky outside the event listener as a cached selector.
 * Also, initialize any needed variables outside the listener for 
 * performance reasons - no variable instantiation is happening inside the listener.
 */
var sticky = $('#sticky'),
    stickyClone,
    stickyTop = sticky.offset().top,
    scrollTop,
    scrolled = false,
    $window = $(window);

/* Bind the scroll Event */
$window.on('scroll', function (e) {
    scrollTop = $window.scrollTop();

    if (scrollTop >= stickyTop && !stickyClone) {
        /* Attach a clone to replace the "missing" body height */
        stickyClone = sticky.clone().prop('id', sticky.prop('id') + '-clone')
        stickyClone = stickyClone.insertBefore(sticky);
        sticky.addClass('fixed');
    } else if (scrollTop < stickyTop && stickyClone) {
        /* Since sticky is in the viewport again, we can remove the clone and the class */
        stickyClone.remove();
        stickyClone = null;
        sticky.removeClass('fixed');
    }
});

CSS

body {
    margin: 0
}
.sticky {
    padding: 1em;
    background: black;
    color: white;
    width: 100%
}
.sticky.fixed {
    position: fixed;
    top: 0;
    left: 0;
}
.content {
    padding: 1em
}

HTML

<div class="container">
  <div id="page-above" class="content">
    <h2>Some Content above sticky</h2>
    ...some long text...
  </div>
  <div id="sticky" class="sticky">This is sticky</div>
  <div id="page-content" class="content">
    <h2>Some Random Page Content</h2>...some really long text...
  </div>
</div>

如果您在布局中使用此功能,但该布局未跨越屏幕宽度,则在滚动时布局将填充屏幕宽度。 - Walter Verhoeven

10

这里是一个简短而简单的代码,没有框架:

var el = document.getElementById('elId');
var elTop = el.getBoundingClientRect().top - document.body.getBoundingClientRect().top;

window.addEventListener('scroll', function(){
    if (document.documentElement.scrollTop > elTop){
        el.style.position = 'fixed';
        el.style.top = '0px';
    }
    else
    {
        el.style.position = 'static';
        el.style.top = 'auto';
    }
});

4
你想使用 jQuery WayPoints。这是一个非常简单的插件,可以实现你所描述的功能。
最直接的实现方式。
    $('.thing').waypoint(function(direction) {
  alert('Top of thing hit top of viewport.');
});

您需要设置一些自定义CSS来确切地设置它停留的位置,但这对于大多数方法来说都是正常的。

此页面将向您展示所有所需的示例和信息。

供参考,此网站是一个“在野外”例子,可以展示它的停止和启动。


1
你可以访问LESS CSS网站http://lesscss.org/ 他们的可停靠菜单轻巧且性能良好。唯一的注意事项是效果在滚动完成后才会发生。只需查看源代码即可查看js。

1

1

纯JavaScript解决方案(演示):

<br/><br/><br/><br/><br/><br/><br/>
<div>
  <div id="myyy_bar" style="background:red;"> Here is window </div>
</div>
<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>


<script type="text/javascript">
var myyElement = document.getElementById("myyy_bar"); 
var EnableConsoleLOGS = true;           //to check the results in Browser's Inspector(Console), whenever you are scrolling
// ==============================================



window.addEventListener('scroll', function (evt) {
    var Positionsss =  GetTopLeft ();  
    if (EnableConsoleLOGS) { console.log(Positionsss); }
    if (Positionsss.toppp  > 70)    { myyElement.style.position="relative"; myyElement.style.top = "0px";  myyElement.style.right = "auto"; }
    else                            { myyElement.style.position="fixed";    myyElement.style.top = "100px";         myyElement.style.right = "0px"; }
});



function GetOffset (object, offset) {
    if (!object) return;
    offset.x += object.offsetLeft;       offset.y += object.offsetTop;
    GetOffset (object.offsetParent, offset);
}
function GetScrolled (object, scrolled) {
    if (!object) return;
    scrolled.x += object.scrollLeft;    scrolled.y += object.scrollTop;
    if (object.tagName.toLowerCase () != "html") {          GetScrolled (object.parentNode, scrolled);        }
}

function GetTopLeft () {
    var offset = {x : 0, y : 0};        GetOffset (myyElement.parentNode, offset);
    var scrolled = {x : 0, y : 0};      GetScrolled (myyElement.parentNode.parentNode, scrolled);
    var posX = offset.x - scrolled.x;   var posY = offset.y - scrolled.y;
    return {lefttt: posX , toppp: posY };
}
// ==============================================
</script>

谢谢!您能否请澄清一下Positionsss.toppp > 70的检查是什么?图片与页面上边缘之间的空间吗?当我在具有不同内容量的页面上运行它时,会提供不同的结果 - 对于具有大量内容的页面,图像跳得太快了。尽管页眉对于两个页面来说大小相同。 - parsecer
1
我看过一些可怕的变量名,但最糟糕的是 Positionsss.toppp。 - Francisco Ochoa

0
我最近使用的解决方案是:
.sticky {
  position: fixed;
  top: 0;
  width: 100%;
}

var header = document.getElementById("filters-tab");
var sticky = header.offsetTop;

if (window.pageYOffset > sticky) {
  header.classList.add("fixed");
} else {
  header.classList.remove("fixed");
}

0
window.addEventListener("scroll", function(evt) {
    var pos_top = document.body.scrollTop;   
    if(pos_top == 0){
       $('#divID').css('position','fixed');
    }

    else if(pos_top > 0){
       $('#divId').css('position','static');
    }
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接