如何使用jQuery使div元素在滚动时平滑跟随?

64

我的容器中有多个部分/盒子,但这些盒子中的最后一个在没有其他盒子可见时应该跟随滚动。

因此,当用户向下滚动时,他会看到一个普通的侧边栏,但当用户滚动到足够低时,侧边栏结束,最后一个盒子开始跟随屏幕顶部。我在不同类型的网站上经常看到这种效果。

目前我的代码:

$(window).scroll(function(){
    $.each($('.follow-scroll'),function(){
        var eloffset = $(this).offset();
        var windowpos = $(window).scrollTop();
        if(windowpos<eloffset.top) {
            var finaldestination = 0;
        } else {
            var finaldestination = windowpos;
        }
        $(this).stop().animate({'top':finaldestination},200);
    });
});

1
@Martti,我删除了我的答案,这样问题就会吸引更多的观众。 - Pekka
4
不错的插件:http://kitchen.net-perspective.com/open-source/scroll-follow/ - rémy
现在许多浏览器都可以通过CSS实现这一点:position: sticky - Martti Laine
10个回答

79

由于这个问题的浏览量很大,而且得票最多的答案中链接的教程似乎已经失效了,所以我花了时间整理了这个脚本。

在此处可以实时查看:JSFiddle

JavaScript:

(function($) {
    var element = $('.follow-scroll'),
        originalY = element.offset().top;

    // Space between element and top of screen (when scrolling)
    var topMargin = 20;

    // Should probably be set in CSS; but here just for emphasis
    element.css('position', 'relative');

    $(window).on('scroll', function(event) {
        var scrollTop = $(window).scrollTop();

        element.stop(false, false).animate({
            top: scrollTop < originalY
                    ? 0
                    : scrollTop - originalY + topMargin
        }, 300);
    });
})(jQuery);

1
我的偏移量是1518。所以我改成了 scrollTop > originalY,并且 topMargin = 200 - Shaiju T
易于实现 - sglessard
1
有什么建议可以让它在底部偏移吗?在某些浏览器窗口中,我发现div会重叠我的页脚。 - Peter Eastwood

52

也许我错过了什么,但如果您的内容是居中的,这不是一个好的解决方案。 - lukkea
1
这是我能找到的最流畅的滚动示例,几乎完美。就像上面提到的许多人一样,唯一的缺点是如果布局居中于页面,则固定div对不同大小的窗口没有所需的影响。有什么想法可以在居中布局上获得相同的效果吗? - JasonDavis
1
由于这个问题得到了很多的浏览量,我决定公正地修改最佳答案的原始选择(这个答案是由我自己提供的)=) - Martti Laine

19
这个方案可以概括为:
var el=$('#follow-scroll');
var elpos=el.offset().top;
$(window).scroll(function () {
    var y=$(this).scrollTop();
    if(y<elpos){el.stop().animate({'top':0},500);}
    else{el.stop().animate({'top':y-elpos},500);}
});

我更改了el的赋值,因为仅通过类来查找单个元素并不是一个好习惯;如果您只想要一个元素,请通过id查找,如果您想要遍历一组元素,则通过类查找它们。

请注意 - 我的答案是针对当时接受的答案(目前仍然是接受的答案,但已被编辑,因此我的答案不再“概括”您在本页面上看到的@Martti Lane的答案;我的答案“概括”了他原始的、接受的答案;如果您有兴趣了解我“概括”的内容,请查看@Martti's答案的编辑历史记录。)


1
谢谢!我用 .css 替换了 .animate 方法(去掉了“,500”),这有助于复制所选答案的结果。 - Shane Reustle
1
这绝对是更优雅的解决方案。 - Ben Liyanage
2
谢谢!好解决方案。测试过:Firefox、Chrome、Safari(MacOsX)完美运行。 - gokhan

5

这个对我起了巨大的帮助。

JavaScript:

$(function() { //doc ready
    if (!($.browser == "msie" && $.browser.version < 7)) {
        var target = "#floating", top = $(target).offset().top - parseFloat($(target).css("margin-top").replace(/auto/, 0));
        $(window).scroll(function(event) {
            if (top <= $(this).scrollTop()) {
                $(target).addClass("fixed");
            } else {
                $(target).removeClass("fixed");
            }
        });
    }
});

CSS:

#floating.fixed{
    position:fixed;
    top:0;
}

来源: http://jqueryfordesigners.com/fixed-floating-elements/

这篇文章介绍了用jQuery处理固定和浮动元素在网页中的布局问题。通过使用CSS定位属性和jQuery脚本,可以实现在滚动页面时固定显示某些元素或者将某些元素浮动到页面上方。具体实现过程详见原文链接。

这在IE9、Chrome、FF和Opera中都可以运行。还没有检查Safari,但希望它也能运行。 - Devner
它对我也起作用了,但我有一个问题。我的网站有水平滚动条,因为内容非常宽。当我垂直滚动窗口时,div浮动,但我无法看到完整的div,因为水平滚动条消失了。有什么建议吗? - rakela
1
这是最佳解决方案,因为横幅静止不动,不会像其他解决方案那样出现丑陋的滚动,从而不会干扰观看者。 - Hexodus

3

这是我最终的代码...(基于之前的修复,非常感谢你的帮助,省去了很多实验时间)。让我困扰的是向上滚动和向下滚动... :)

总是让我想知道 jQuery 怎么这么优雅啊!!!

$(document).ready(function(){

    //run once
    var el=$('#scrolldiv');
    var originalelpos=el.offset().top; // take it where it originally is on the page

    //run on scroll
     $(window).scroll(function(){
        var el = $('#scrolldiv'); // important! (local)
        var elpos = el.offset().top; // take current situation
        var windowpos = $(window).scrollTop();
        var finaldestination = windowpos+originalelpos;
        el.stop().animate({'top':finaldestination},500);
     });

});

3

以下是我的解决方案(希望它也足够易于使用):

  1. 复制JS代码部分
  2. 将'slide-along-scroll'类添加到您想要的元素中
  3. 在JS代码中进行像素级的纠正
  4. 希望您会喜欢它!

// SlideAlongScroll
var SlideAlongScroll = function(el) {
  var _this = this;
  this.el = el;
  // elements original position
  this.elpos_original = el.parent().offset().top;  
  // scroller timeout
  this.scroller_timeout;
  // scroller calculate function
  this.scroll = function() {
    // 20px gap for beauty
    var windowpos = $(window).scrollTop() + 20;
    // targeted destination
    var finaldestination = windowpos - this.elpos_original;
    // define stopper object and correction amount
    var stopper = ($('.footer').offset().top); // $(window).height() if you dont need it
    var stophere = stopper - el.outerHeight() - this.elpos_original - 20;
    // decide what to do
    var realdestination = 0;
    if(windowpos > this.elpos_original) {
      if(finaldestination >= stophere) {
        realdestination = stophere;
      } else {
        realdestination = finaldestination;
      }
    }
    el.css({'top': realdestination });
  };
  // scroll listener
  $(window).on('scroll', function() {
    // debounce it
    clearTimeout(_this.scroller_timeout);
    // set scroll calculation timeout
    _this.scroller_timeout = setTimeout(function() { _this.scroll(); }, 300);
  });
  // initial position (in case page is pre-scrolled by browser after load)
  this.scroll();
};
// init action, little timeout for smoothness
$(document).ready(function() {
  $('.slide-along-scroll').each(function(i, el) {
    setTimeout(function(el) { new SlideAlongScroll(el); }, 300, $(el));
  });
});
/* part you need */
.slide-along-scroll {
  padding: 20px;
  background-color: #CCCCCC;
 transition: top 300ms ease-out;
 position: relative;
}
/* just demo */
div {  
  box-sizing: border-box;
}
.side-column {
  float: left;
  width: 20%;    
}
.main-column {
  padding: 20px;
  float: right;
  width: 75%;
  min-height: 1200px;
  background-color: #EEEEEE;
}
.body {  
  padding: 20px 0;  
}
.body:after {
  content: ' ';
  clear: both;
  display: table;
}
.header {
  padding: 20px;
  text-align: center;
  border-bottom: 2px solid #CCCCCC;  
}
.footer {
  padding: 20px;
  border-top: 2px solid #CCCCCC;
  min-height: 300px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
  <div class="header">
      <h1>Your super-duper website</h1>
  </div>
  <div class="body">  
    <div class="side-column">
        <!-- part you need -->
        <div class="slide-along-scroll">
            Side menu content
            <ul>
               <li>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</li>
               <li>Aliquam tincidunt mauris eu risus.</li>
               <li>Vestibulum auctor dapibus neque.</li>
            </ul>         
        </div>
    </div>
    <div class="main-column">
        Main content area (1200px)
    </div>
  </div>
  <div class="footer">
      Footer (slide along is limited by it)
  </div>
</div>


2
我需要 div 到达特定对象时停止,所以我这样做:

当 div 到达特定对象时,我将其停止:

var el = $('#followdeal');
    var elpos_original = el.offset().top;
    $(window).scroll(function(){
        var elpos = el.offset().top;
        var windowpos = $(window).scrollTop();
        var finaldestination = windowpos;
        var stophere = ( $('#filtering').offset().top ) - 170;
        if(windowpos<elpos_original || windowpos>=stophere) {
            finaldestination = elpos_original;
            el.stop().animate({'top':10});
        } else {
            el.stop().animate({'top':finaldestination-elpos_original+10},500);
        }
    });

你好, 我想在我的网站上使用这种技术。这是结构:
Lorem ipsum....
<div id="footer"> </div> </div> 我希望# ad div随着页面滚动,但只有当所有侧边栏子div消失时(在这种情况下为# sidebar_div1和# sideba_div2)。 这可能吗? - Pennywise83

2

那段代码并不太好用, 我稍微修复了一下

var el = $('.caja-pago');
var elpos_original = el.offset().top;

 $(window).scroll(function(){
     var elpos = el.offset().top;
     var windowpos = $(window).scrollTop();
     var finaldestination = windowpos;
     if(windowpos<elpos_original) {
         finaldestination = elpos_original;
         el.stop().animate({'top':400},500);
     } else {
         el.stop().animate({'top':windowpos+10},500);
     }
 });

1

This one is same on facebook:

<script>
var valX = $(window).scrollTop();
function syncScroll(target){
 var valY = $(window).scrollTop();
 var difYX = valY - valX;
 var targetX = $(target).scrollTop();
 if(valY > valX){
  $(target).scrollTop(difYX);
 }
 if(difYX <= 0){
  $(target).scrollTop(-20);
 }
}

$(window).scroll(function(){
 syncScroll('#demo');
})
</script>
body{
  margin:0;
  padding:0;
  height:100%;
}
#demo{
  position:fixed;
  height:100vh;
  overflow:hidden;
  width:40%;
}
#content{
  position:relative;
  float:right;
  width:60%;
  color:red; 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<body>
  <div id="demo">
    <ul>
      <li>
        <p>"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."</p>
      </li>
      <li>
        <p>
"Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?"
        </p>
      </li>  
      <li>
        <p>
"But I must explain to you how all this mistaken idea of denouncing pleasure and praising pain was born and I will give you a complete account of the system, and expound the actual teachings of the great explorer of the truth, the master-builder of human happiness. No one rejects, dislikes, or avoids pleasure itself, because it is pleasure, but because those who do not know how to pursue pleasure rationally encounter consequences that are extremely painful. Nor again is there anyone who loves or pursues or desires to obtain pain of itself, because it is pain, but because occasionally circumstances occur in which toil and pain can procure him some great pleasure. To take a trivial example, which of us ever undertakes laborious physical exercise, except to obtain some advantage from it? But who has any right to find fault with a man who chooses to enjoy a pleasure that has no annoying consequences, or one who avoids a pain that produces no resultant pleasure?"
        </p>
      </li>
    <ul>
  </div>
  <div id="content">
    <ul>
      <li>
        <p>"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."</p>
      </li>
      <li>
        <p>
"Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?"
        </p>
      </li>  
      <li>
        <p>
"But I must explain to you how all this mistaken idea of denouncing pleasure and praising pain was born and I will give you a complete account of the system, and expound the actual teachings of the great explorer of the truth, the master-builder of human happiness. No one rejects, dislikes, or avoids pleasure itself, because it is pleasure, but because those who do not know how to pursue pleasure rationally encounter consequences that are extremely painful. Nor again is there anyone who loves or pursues or desires to obtain pain of itself, because it is pain, but because occasionally circumstances occur in which toil and pain can procure him some great pleasure. To take a trivial example, which of us ever undertakes laborious physical exercise, except to obtain some advantage from it? But who has any right to find fault with a man who chooses to enjoy a pleasure that has no annoying consequences, or one who avoids a pain that produces no resultant pleasure?"
        </p>
      </li>
      <li>
        <p>"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."</p>
      </li>
      <li>
        <p>
"Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?"
        </p>
      </li>  
      <li>
        <p>
"But I must explain to you how all this mistaken idea of denouncing pleasure and praising pain was born and I will give you a complete account of the system, and expound the actual teachings of the great explorer of the truth, the master-builder of human happiness. No one rejects, dislikes, or avoids pleasure itself, because it is pleasure, but because those who do not know how to pursue pleasure rationally encounter consequences that are extremely painful. Nor again is there anyone who loves or pursues or desires to obtain pain of itself, because it is pain, but because occasionally circumstances occur in which toil and pain can procure him some great pleasure. To take a trivial example, which of us ever undertakes laborious physical exercise, except to obtain some advantage from it? But who has any right to find fault with a man who chooses to enjoy a pleasure that has no annoying consequences, or one who avoids a pain that produces no resultant pleasure?"
        </p>
      </li>
      <li>
        <p>"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."</p>
      </li>
      <li>
        <p>
"Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?"
        </p>
      </li>  
      <li>
        <p>
"But I must explain to you how all this mistaken idea of denouncing pleasure and praising pain was born and I will give you a complete account of the system, and expound the actual teachings of the great explorer of the truth, the master-builder of human happiness. No one rejects, dislikes, or avoids pleasure itself, because it is pleasure, but because those who do not know how to pursue pleasure rationally encounter consequences that are extremely painful. Nor again is there anyone who loves or pursues or desires to obtain pain of itself, because it is pain, but because occasionally circumstances occur in which toil and pain can procure him some great pleasure. To take a trivial example, which of us ever undertakes laborious physical exercise, except to obtain some advantage from it? But who has any right to find fault with a man who chooses to enjoy a pleasure that has no annoying consequences, or one who avoids a pain that produces no resultant pleasure?"
        </p>
      </li>
      <li>
        <p>"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."</p>
      </li>
      <li>
        <p>
"Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?"
        </p>
      </li>  
      <li>
        <p>
"But I must explain to you how all this mistaken idea of denouncing pleasure and praising pain was born and I will give you a complete account of the system, and expound the actual teachings of the great explorer of the truth, the master-builder of human happiness. No one rejects, dislikes, or avoids pleasure itself, because it is pleasure, but because those who do not know how to pursue pleasure rationally encounter consequences that are extremely painful. Nor again is there anyone who loves or pursues or desires to obtain pain of itself, because it is pain, but because occasionally circumstances occur in which toil and pain can procure him some great pleasure. To take a trivial example, which of us ever undertakes laborious physical exercise, except to obtain some advantage from it? But who has any right to find fault with a man who chooses to enjoy a pleasure that has no annoying consequences, or one who avoids a pain that produces no resultant pleasure?"
        </p>
      </li>
    <ul>
   </div>   
</body


0
我为这个问题写了一个相对简单的答案。
我有一个表格正在使用一个“sticky table header”插件,在我的页面上紧贴在特定div的下方,但是表格左侧的菜单没有粘住(因为它不是表格的一部分)。
为了我的目的,我知道需要“粘性”的div始终会从窗口顶部以下385像素开始,因此我在其上方创建了一个空的div:
<div id="stopMenu" class="stopMenu"></div>

然后运行了这个:

$(window).scroll(function(){   
   if ( $(window).scrollTop() > 385 ) {
    extraPadding = $(window).scrollTop() - 385;
    $('#stopMenu').css( "padding-top", extraPadding );
   } else {
     $('#stopMenu').css( "padding-top", "0" );
   }
});

随着用户的滚动,它会将 $(window).scrollTop() 的值加到整数 385 上,然后将该值添加到我想要保持焦点的对象上面的 stopMenu div 中。
如果用户返回到顶部,我只需将额外的填充设置为0。
这不需要特别在CSS中做任何事情,但这是一种很好的效果,可以使小延迟,因此我也加入了 class="stopMenu"
.stopMenu {
  .transition: all 0.1s;
}

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