jQuery 粘性侧边栏:向下滚动时粘在底部,向上滚动时粘在顶部
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18358816/
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
Sticky sidebar: stick to bottom when scrolling down, top when scrolling up
提问by andbamnan
I have been looking for some time now for a solution to my sticky sidebar problem. I have a specific idea of how I would like it to act; effectively, I would like it to stick to the bottom as you scroll down, and then as soon as you scroll back up I would like it to stick to the top, in a fluid motion (no jumping). I am unable to find an example of what I am trying to achieve, so I have created an image that I hope will illustrate the point clearer:
我一直在寻找解决我的侧边栏粘性问题的方法。我对我希望它如何行动有一个具体的想法;实际上,我希望它在您向下滚动时粘在底部,然后一旦您向上滚动,我希望它以流畅的运动(不跳跃)粘在顶部。我无法找到我想要实现的目标的示例,因此我创建了一个图像,希望能更清楚地说明这一点:
- Sidebar sits under the header.
- As you scroll down the sidebar remains level with the content of the page so that you can scroll through both sidebar and content.
- Reach the bottom of the sidebar, the sidebar sticks to the bottom of the viewport (most plugins only allow for sticking to top, some that allow for sticking to bottom don't allow for both).
- Reach the bottom, sidebar sits above the footer.
- As you scroll back up, the sidebar stays level with the content so you can scroll through the content and sidebar again.
- Reach the top of the sidebar, the sidebar sticks to the top of the viewport.
- Reach the top and the sidebar sits back below the header.
- 侧边栏位于标题下方。
- 当您向下滚动时,侧边栏与页面内容保持水平,以便您可以滚动侧边栏和内容。
- 到达侧边栏的底部,侧边栏粘在视口的底部(大多数插件只允许粘在顶部,一些允许粘在底部的插件不允许两者兼有)。
- 到达底部,侧边栏位于页脚上方。
- 当您向上滚动时,侧边栏与内容保持水平,因此您可以再次滚动浏览内容和侧边栏。
- 到达侧边栏的顶部,侧边栏粘在视口的顶部。
- 到达顶部,侧边栏位于标题下方。
I hope this is enough information. I have created a jsfiddle to test any plugins/scripts, which I have reset for this question: http://jsfiddle.net/jslucas/yr9gV/2/.
我希望这是足够的信息。我创建了一个 jsfiddle 来测试任何插件/脚本,我已经针对这个问题重置了它:http: //jsfiddle.net/jslucas/yr9gV/2/.
采纳答案by gmo
+1to the very nice and ilustrative image.
+1非常漂亮和说明性的图像。
I know it's an old question, but I casually found the same question posted by you in forum.jquery.comand one answer there (by@tucker973), suggested one nice library to make this and wanted to share it here.
我知道这是一个老问题,但我偶然发现了您在forum.jquery.com 上发布的相同问题,并在那里找到了一个答案(by@tucker973),建议使用一个不错的库来制作这个,并想在这里分享。
It's called sticky-kitby @leafo
它被@leafo称为sticky-kit
- github proyect
- webpage
- simple example in jsFiddle(same code as the snippet attached here)
- github项目
- 网页
- jsFiddle 中的简单示例(与此处附加的代码段相同)
Here you have the code of a very basic example that I prepared and a working demo to see the result.
这里有我准备的一个非常基本的例子的代码和一个工作演示来查看结果。
/*!
* 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>
Of course, all credits go to the creator of the plugin, I only made this example to show it here. I need to accomplish the same result that you was after and found this plugin very useful.
当然,所有的功劳都归于插件的创建者,我只是在这里制作了这个例子来展示它。我需要完成您所追求的相同结果,并发现此插件非常有用。
回答by Travis Kriplean
Thanks for the great graphic. I was also looking for a solution to this challenge!
感谢伟大的图形。我也在寻找这个挑战的解决方案!
Unfortunately, the other answer posted here doesn't address requirement #5 that stipulates the ability to scroll back through the sidebar smoothly.
不幸的是,这里发布的另一个答案没有解决要求#5,该要求规定能够平滑地向后滚动侧边栏。
I created a fiddle that implements all requirements: http://jsfiddle.net/bN4qu/5/
我创建了一个实现所有要求的小提琴:http: //jsfiddle.net/bN4qu/5/
The core logic that needs to be implemented is:
需要实现的核心逻辑是:
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
In the fiddle I use CSS3 transform for moving the target element around, so it won't work in e.g. IE<9. The logic is sound though for using a different approach.
在小提琴中,我使用 CSS3 变换来移动目标元素,因此它在 IE<9 中不起作用。尽管使用不同的方法,逻辑是合理的。
Also, I modified your fiddle so that the sticky sidebar has a gradient background. This helps to show that the proper behavior is being exhibited.
此外,我修改了您的小提琴,以便粘性侧边栏具有渐变背景。这有助于表明正在展示正确的行为。
I hope this is useful to someone!
我希望这对某人有用!
回答by Anoop Naik
Here's an example of how to implement this:
下面是如何实现这一点的示例:
JavaScript:
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:
CSS:
#sidebar {
width: 180px;
padding: 10px;
background: red;
float: right;
}
.fixed {
position: fixed;
right: 50%;
margin-right: -50%;
}
Demo:http://jsfiddle.net/ryanmaxwell/25QaE/
演示:http : //jsfiddle.net/ryanmaxwell/25QaE/
This works as expected in all scenarios and is well-supported in IE too.
这在所有场景中都按预期工作,并且在 IE 中也得到了很好的支持。
回答by Manju Talluri
There is a relatively unknown plugin in Wordpress repository known as WP Sticky Sidebar. The plugin does exactly what you wanted (Sticky sidebar: stick to bottom when scrolling down, top when scrolling up) WP Sticky Sidebar Wordpress repository Link: https://wordpress.org/plugins/mystickysidebar/
Wordpress 存储库中有一个相对不为人知的插件,称为 WP Sticky Sidebar。该插件完全符合您的要求(粘性侧边栏:向下滚动时粘在底部,向上滚动时粘在顶部)WP 粘性侧边栏 Wordpress 存储库链接:https: //wordpress.org/plugins/mystickysidebar/
回答by SezginOnline
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");
Working Example:https://jsfiddle.net/L7xoopst/6/
工作示例:https : //jsfiddle.net/L7xoopst/6/
回答by callmeforsox
I was looking for the exact same thing. Apparently I needed to search for some obscure terms just to find a similar question with the graphic. Turns out it's exactly what I was looking for. I couldn't find any plugins so I decided to make it myself. Hopefully someone will see this and refine it.
我正在寻找完全相同的东西。显然,我需要搜索一些晦涩的术语才能找到与图形类似的问题。原来这正是我要找的。我找不到任何插件,所以我决定自己制作。希望有人会看到并完善它。
Here's a quick and dirty sample html I'm using.
这是我正在使用的一个快速而肮脏的示例 html。
<div id="main">
<div class="col-1">
</div>
<div class="col-2">
<div class="side-wrapper">
sidebar content
</div>
</div>
</div>
Here's the jQuery I made:
这是我制作的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();
});
}
Some notes:
一些注意事项:
- .rectbtfad is the bottom most element in my sidebar
- I'm using the height of my #masthead because it's a sticky header so it needs to compensate for it
- There's a check for col-2 float since I'm using a responsive design and don't want this activating on smaller screens
- .rectbtfad 是我侧边栏中最底部的元素
- 我正在使用 #masthead 的高度,因为它是一个粘性标题,因此需要对其进行补偿
- 由于我使用的是响应式设计并且不希望在较小的屏幕上激活它,因此检查了 col-2 浮动
If anyone can refine this a bit more that'd be great.
如果有人可以进一步完善这一点,那就太好了。