粘滞边栏:向下滚动时贴在底部,向上滚动时贴在顶部

我一直在寻找一些解决我的粘滞边栏问题的时间。 我有一个特定的想法,我希望如何行动; 有效地,当你向下滚动时,我希望它坚持到底部,然后当你向后滚动时,我想它会以stream畅的运动(不跳跃)粘到顶部。 我无法find我想要达到的一个例子,所以我创造了一个我希望能够更清楚地表明这一点的图像:

粘滞边栏:向下滚动时贴在底部,向上滚动时贴在顶部

  1. 侧栏位于标题下。
  2. 在向下滚动时,侧边栏与页面的内容保持水平,以便您可以滚动浏览侧边栏和内容。
  3. 到达侧边栏的底部,侧边栏粘贴到视口的底部(大多数插件只允许粘贴到顶部,有些粘贴到底部不允许)。
  4. 触及底部,侧边栏位于页脚上方。
  5. 当您向后滚动时,侧边栏与内容保持水平,因此您可以再次滚动内容和边栏。
  6. 到达侧栏的顶部,侧栏粘贴到视口的顶部。
  7. 到达顶部和侧边栏位于标题下方。

我希望这是足够的信息。 我创build了一个jsfiddle来testing任何插件/脚本,我已经重置了这个问题: http : //jsfiddle.net/jslucas/yr9gV/2/ .

非常感谢,如果有人有我的解决scheme。

对非常好看的图像+1

我知道这是一个古老的问题,但我随便find了你在forum.jquery.com上发布的同一个问题,并在那里find了一个答案(by @ tucker973) ,提出了一个很好的库来做到这一点,并希望在这里分享。

它被@leafo称为sticky-kit

  • github proyect
  • 网页
  • jsFiddle中的简单示例 (与此处附带的代码段相同的代码)

在这里,你有我编写的一个非常基本的例子的代码和一个工作演示来看看结果。

 /*! * Sticky-kit * A jQuery plugin for making smart sticky elements * * Source: http://leafo.net/sticky-kit/ */ $(function() { $(".sidebar").stick_in_parent({ offset_top: 10 }); }); 
 * { font-size: 10px; color: #333; box-sizing: border-box; } .wrapper, .header, .main, .footer { padding: 10px; position: relative; } .wrapper { border: 1px solid #333; background-color: #f5f5f5; padding: 10px; } .header { background-color: #6289AE; margin-bottom: 10px; height: 100px; } .sidebar { position: absolute; padding: 10px; background-color: #ccc; height: 300px; width: 100px; float: left; } .main { background-color: #ccc; height: 600px; margin-left: 110px; } .footer { background-color: #6289AE; margin-top: 10px; height: 250px; } .top { position: absolute; top: 10px; } .bottom { position: absolute; bottom: 10px; } .clear { clear: both; float: none; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <script src="http://leafo.net/sticky-kit/src/jquery.sticky-kit.js"></script> <div class="wrapper"> <div class="header"> <a class="top">header top</a> <a class="bottom">header bottom</a> </div> <div class="content"> <div class="sidebar"> <a class="top">sidebar top</a> <a class="bottom">sidebar bottom</a> </div> <div class="main"> <a class="top">main top</a> <a class="bottom">main bottom</a> </div> <div class="clear"></div> </div> <div class="footer"> <a class="top">footer top</a> <a class="bottom">footer bottom</a> </div> </div> 

感谢伟大的graphics。 我也在寻找解决这个挑战的方法!

不幸的是,这里发布的其他答案并不涉及要求#5,它规定了平滑地回滚侧边栏的能力。

我创build了一个实现所有要求的小提琴: http : //jsfiddle.net/bN4qu/5/

需要实施的核心逻辑是:

 If scrolling up OR the element is shorter than viewport Then Set top of element to top of viewport If scrolled above top of element If scrolling down then Set bottom of element at bottom of viewport If scrolled past bottom of element 

在小提琴中,我使用CSS3变换来移动目标元素,所以它不能在IE <9中工作。 尽pipe使用不同的方法,但逻辑是合理的。

另外,我修改了你的小提琴,让粘滞侧栏有一个渐变的背景。 这有助于表明正确的行为正在展示。

我希望这对某个人有用!

这是一个如何实现这个的例子:

JavaScript的:

 $(function() { var $window = $(window); var lastScrollTop = $window.scrollTop(); var wasScrollingDown = true; var $sidebar = $("#sidebar"); if ($sidebar.length > 0) { var initialSidebarTop = $sidebar.position().top; $window.scroll(function(event) { var windowHeight = $window.height(); var sidebarHeight = $sidebar.outerHeight(); var scrollTop = $window.scrollTop(); var scrollBottom = scrollTop + windowHeight; var sidebarTop = $sidebar.position().top; var sidebarBottom = sidebarTop + sidebarHeight; var heightDelta = Math.abs(windowHeight - sidebarHeight); var scrollDelta = lastScrollTop - scrollTop; var isScrollingDown = (scrollTop > lastScrollTop); var isWindowLarger = (windowHeight > sidebarHeight); if ((isWindowLarger && scrollTop > initialSidebarTop) || (!isWindowLarger && scrollTop > initialSidebarTop + heightDelta)) { $sidebar.addClass('fixed'); } else if (!isScrollingDown && scrollTop <= initialSidebarTop) { $sidebar.removeClass('fixed'); } var dragBottomDown = (sidebarBottom <= scrollBottom && isScrollingDown); var dragTopUp = (sidebarTop >= scrollTop && !isScrollingDown); if (dragBottomDown) { if (isWindowLarger) { $sidebar.css('top', 0); } else { $sidebar.css('top', -heightDelta); } } else if (dragTopUp) { $sidebar.css('top', 0); } else if ($sidebar.hasClass('fixed')) { var currentTop = parseInt($sidebar.css('top'), 10); var minTop = -heightDelta; var scrolledTop = currentTop + scrollDelta; var isPageAtBottom = (scrollTop + windowHeight >= $(document).height()); var newTop = (isPageAtBottom) ? minTop : scrolledTop; $sidebar.css('top', newTop); } lastScrollTop = scrollTop; wasScrollingDown = isScrollingDown; }); } }); 

CSS:

 #sidebar { width: 180px; padding: 10px; background: red; float: right; } .fixed { position: fixed; right: 50%; margin-right: -50%; } 

演示: http : //jsfiddle.net/ryanmaxwell/25QaE/

这在所有情况下都能按预期运行,并且在IE中也得到了很好的支持。

 function fixMe(id) { var e = $(id); var lastScrollTop = 0; var firstOffset = e.offset().top; var lastA = e.offset().top; var isFixed = false; $(window).scroll(function(event){ if (isFixed) { return; } var a = e.offset().top; var b = e.height(); var c = $(window).height(); var d = $(window).scrollTop(); if (b <= c - a) { e.css({position: "fixed"}); isFixed = true; return; } if (d > lastScrollTop){ // scroll down if (e.css("position") != "fixed" && c + d >= a + b) { e.css({position: "fixed", bottom: 0, top: "auto"}); } if (a - d >= firstOffset) { e.css({position: "absolute", bottom: "auto", top: lastA}); } } else { // scroll up if (a - d >= firstOffset) { if (e.css("position") != "fixed") { e.css({position: "fixed", bottom: "auto", top: firstOffset}); } } else { if (e.css("position") != "absolute") { e.css({position: "absolute", bottom: "auto", top: lastA}); } } } lastScrollTop = d; lastA = a; }); } fixMe("#stick"); 

工作示例: https //jsfiddle.net/L7xoopst/6/

我正在寻找完全一样的东西。 显然,我需要search一些模糊的术语,只是为了find与graphics类似的问题。 原来,这正是我在找的东西。 我找不到任何插件,所以我决定自己做。 希望有人会看到这一点,并完善它。

这里有一个快速和肮脏的示例HTML我正在使用。

 <div id="main"> <div class="col-1"> </div> <div class="col-2"> <div class="side-wrapper"> sidebar content </div> </div> </div> 

这是我做的jQuery:

 var lastScrollPos = $(window).scrollTop(); var originalPos = $('.side-wrapper').offset().top; if ($('.col-2').css('float') != 'none') { $(window).scroll(function(){ var rectbtfadPos = $('.rectbtfad').offset().top + $('.rectbtfad').height(); // scroll up direction if ( lastScrollPos > $(window).scrollTop() ) { // unstick if scrolling the opposite direction so content will scroll with user if ($('.side-wrapper').css('position') == 'fixed') { $('.side-wrapper').css({ 'position': 'absolute', 'top': $('.side-wrapper').offset().top + 'px', 'bottom': 'auto' }); } // if has reached the original position, return to relative positioning if ( ($(window).scrollTop() + $('#masthead').height()) < originalPos ) { $('.side-wrapper').css({ 'position': 'relative', 'top': 'auto', 'bottom': 'auto' }); } // sticky to top if scroll past top of sidebar else if ( ($(window).scrollTop() + $('#masthead').height()) < $('.side-wrapper').offset().top && $('.side-wrapper').css('position') == 'absolute' ) { $('.side-wrapper').css({ 'position': 'fixed', 'top': 15 + $('#masthead').height() + 'px', // padding to compensate for sticky header 'bottom': 'auto' }); } } // scroll down else { // unstick if scrolling the opposite direction so content will scroll with user if ($('.side-wrapper').css('position') == 'fixed') { $('.side-wrapper').css({ 'position': 'absolute', 'top': $('.side-wrapper').offset().top + 'px', 'bottom': 'auto' }); } // check if rectbtfad (bottom most element) has reached the bottom if ( ($(window).scrollTop() + $(window).height()) > rectbtfadPos && $('.side-wrapper').css('position') != 'fixed' ) { $('.side-wrapper').css({ 'width': $('.col-2').width(), 'position': 'fixed', 'bottom': '0', 'top': 'auto' }); } } // set last scroll position to determine if scrolling up or down lastScrollPos = $(window).scrollTop(); }); } 

一些说明:

  • .rectbtfad是我的边栏中最底层的元素
  • 我正在使用我的#masthead的高度,因为它是一个粘性头,所以它需要补偿
  • 有一个检查col-2浮法,因为我使用的是一个响应式devise,不希望在小屏幕上激活

如果任何人都可以改善这一点,那会更好。