(嘿,来自长期潜伏者的第一篇文章:)
我已经构建了一个简单的侧边栏,可以将“absolute-to-fixed”技巧留在屏幕上,但是想要考虑侧边栏高于视口的帐户情况。
所以我提出了这个想法。一切都从上面开始:
但是这里变得更有活力:
如果侧边栏比视口高,则继续以滚动内容,直到到达侧边栏的底部,并在那里修复。侧边栏的顶部滚动到视口顶部之外。
当用户向页面顶部滚动时,侧边栏会随内容一起移动,直到到达侧边栏的顶部,然后它就会修复。侧边栏的底部滚动到视口底部之外。
通过这种方式,侧边栏像往常一样对滚动作出反应,同时保持足够接近以便在长页面上找到。
任何指向示例的指针,或jQuery友好的代码片段/指南都将非常感激。
答案 0 :(得分:20)
我对项目有这个确切的想法,这是一个如何实现它的例子
答案 1 :(得分:3)
您希望实现的行为称为“词缀”。 Twitter的Bootstrap前端框架有一个javascript组件,可以做你想要的。请检查section about the affix component。事实上,在那里你还可以看到所需行为的演示,左侧边栏中的菜单被贴上了。
您可以为affix init调用的offset参数定义函数,因此可以动态确定何时固定/取消固定元素。要查看上下文中的示例,请检查上述链接页面的来源,特别是查找application.js
,它包含您可以在左侧看到的词缀设置。在这里,您可以看到脱离上下文的初始化代码:
// side bar
$('.bs-docs-sidenav').affix({
offset: {
top: function () { return $window.width() <= 980 ? 290 : 210 }
, bottom: 270
}
})
在页面来源中检查docs.css
样式表可能也是值得的,其中包含了附加元素的一些定位和样式。检查这可能会解决您的问题,或至少可以给您和想法。
答案 2 :(得分:1)
由于这些例子都不适合我,我这样做了,我喜欢分享:
<强> JS 强>
$(function () {
var element = $('.right-container');
var originalY = element.offset().top;
var lastOffset = $(document).scrollTop();
var diffToBottom = element.height() - $(window).height();
$(window).on('scroll', function (event) {
var scrollTop = $(window).scrollTop();
var currentOffset = $(document).scrollTop();
var isScrollingDown = currentOffset > lastOffset;
if (scrollTop > (diffToBottom + element.height())) {
if (!element.hasClass('relative')) {
element.css('top', scrollTop - (originalY + diffToBottom) + 'px');
element.addClass('relative');
}
if (isScrollingDown) {
var newTop = scrollTop < lastOffset ? 0 : scrollTop - (originalY + diffToBottom);
}
else if (scrollTop < element.offset().top) {
var newTop = scrollTop - (originalY);
}
element.stop(false, false).animate({
top: newTop
}, 300);
}
else {
if (scrollTop < originalY) {
element.removeClass('relative');
}
element.stop(false, false).animate({
top: scrollTop - (originalY)
}, 300);
}
lastOffset = currentOffset;
});
});
<强> CSS 强>
.relative {
position: relative;
}
当元素击中底部时它向下滚动,当顶部被击中时向上滚动。
答案 3 :(得分:1)
你可以使用Sticky Sidebar https://abouolia.github.io/sticky-sidebar/#examples
您需要“可滚动粘性元素”行为 请参阅此处示例https://abouolia.github.io/sticky-sidebar/examples/scrollable-element.html
答案 4 :(得分:0)
这样的事可能有用。我没有测试过,但理论上它看起来不错。
$(function(){
var standardPosition = $('whatYouWantToScroll').offset().top;
// Cache the standard position of the scrolling element
$(window).scroll(function() {
if ($(this).scrollTop() < standardPosition) {
// if scroll pos is higher than the top of the element
$('whatYouWantToScroll').css({
position: 'relative',
top: '0px'
});
} else if ($(window).scrollTop() > $('somethingToReferenceOnTheBottom').offset().top-($('whatYouWantToScroll').height())) {
// if scroll position is lower than the top offset of the bottom reference
// + the element that is scrolling height
$('whatYouWantToScroll').css({
position: 'absolute',
top: $('somethingToReferenceOnTheBottom').offset().top-($('whatYouWantToScroll').height())
});
} else {
// otherwise we're somewhere inbetween, fixed scrolling.
$('whatYouWantToScroll').css({
position: 'fixed'
});
}
});
});
答案 5 :(得分:0)
我需要这个网站的确切功能,这就是我提出的,它似乎工作得非常好......我知道这篇文章很老,但我认为有些人可能对此感兴趣; )
(function($){
$(document).ready(function(){
sidebar_offset=$('#header').height()+10;
$(window).scroll(function(){
var sidebar=$('#primary');
if($(this).scrollTop()<sidebar_offset){
var height=$(window).height()-(sidebar_offset-$(this).scrollTop());
css={height:height,marginTop:0};
sidebar[0].scrollTop=0;
}else{
css.height=$(this).height();
if($(this).scrollTop()>sidebar_offset){
if(this.lastTop>$(this).scrollTop()){
sidebar[0].scrollTop=sidebar[0].scrollTop-(this.lastTop-$(this).scrollTop());
}else{
sidebar[0].scrollTop=sidebar[0].scrollTop+($(this).scrollTop()-this.lastTop);
}
css.marginTop=($(this).scrollTop()-sidebar_offset)+'px';
}else{
sidebar[0].scrollTop=0;
}
}
sidebar.css(css);
this.lastTop=$(this).scrollTop();
});
})(jQuery);
答案 6 :(得分:0)
您还要求举例;我经常遇到的一个例子是Facebook右栏广告。它比视口高,滚过第一个或第二个广告,在第三个广告停止。我认为这是由第三个广告的位置而不是侧边栏的整体高度来定义的,但这是一个有效的例子。
screenhots: http://i.imgur.com/dM3OZ.jpg /页面顶部 http://i.imgur.com/SxEZO.jpg /进一步向下
答案 7 :(得分:0)
这是纯javascript中非常有效且通用的代码:
//aside is your sidebar selector
var aside = document.querySelector('aside');
//sticky sidebar on scrolling
var startScroll = aside.offsetTop;
var endScroll = window.innerHeight - aside.offsetHeight;
var currPos = window.scrollY;
document.addEventListener('scroll', () => {
var asideTop = parseInt(aside.style.top.replace('px;', ''));
if (window.scrollY < currPos) {
//scroll up
if (asideTop < startScroll) {
aside.style.top = (asideTop + currPos - window.scrollY) + 'px';
} else if (asideTop > startScroll && asideTop != startScroll) {
aside.style.top = startScroll + 'px';
}
} else {
//scroll down
if (asideTop > endScroll) {
aside.style.top = (asideTop + currPos - window.scrollY) + 'px';
} else if (asideTop < (endScroll) && asideTop != endScroll) {
aside.style.top = endScroll + 'px';
}
}
currPos = window.scrollY;
});
//this code will bring to you sidebar on refresh page
function asideToMe() {
setTimeout(() => {
aside.style.top = startScroll + 'px';
}, 300);
}
asideToMe();
body{
padding: 0 20px;
}
#content {
height: 1200px;
}
header {
width: 100%;
height: 150px;
background: #aaa;
}
main {
float: left;
width: 65%;
height: 100%;
background: linear-gradient(180deg, rgba(255,255,255,1) 0%, rgba(0,0,0,1) 100%);
}
aside {
float: right;
width: 30%;
height: 800px;
position: sticky;
top: 100px;
background: linear-gradient(0deg, rgba(2,0,36,1) 0%, rgba(22,153,66,1) 51%, rgba(167,255,0,1) 100%);
}
footer {
width: 100%;
height: 70px;
background: #555;
}
<body>
<header>Header</header>
<div id="content">
<main>Content</main>
<aside>Sidebar</aside>
</div>
<footer>Footer</footer>
</body>
答案 8 :(得分:0)
Juste在没有jQuery(香草JS)的情况下制作了@Ryan JsFiddle的叉子:
https://jsfiddle.net/Kalane/8w09orvg/6/
function getOffset(el) {
const win = el.ownerDocument.defaultView
const rect = el.getBoundingClientRect()
return {
top: rect.top + win.pageYOffset,
left: rect.left + win.pageXOffset
}
}
function getPosition(el) {
const offset = this.getOffset(el)
const parentOffset = this.getOffset(el.parentNode)
return {
top: offset.top - parentOffset.top,
left: offset.left - parentOffset.left,
}
}
let lastScrollTop = document.documentElement.scrollTop
let wasScrollingDown = true
const sidebar = document.querySelector('#sidebar')
const initialSidebarTop = getPosition(sidebar).top
window.addEventListener('scroll', () => {
const windowHeight = window.innerHeight
const sidebarHeight = Math.ceil(sidebar.getBoundingClientRect().height)
const scrollTop = document.documentElement.scrollTop
const scrollBottom = scrollTop + windowHeight
const sidebarTop = getPosition(sidebar).top
const sidebarBottom = sidebarTop + sidebarHeight
const heightDelta = Math.abs(windowHeight - sidebarHeight)
const scrollDelta = lastScrollTop - scrollTop
const isScrollingDown = (scrollTop > lastScrollTop)
const isWindowLarger = (windowHeight > sidebarHeight)
if ((isWindowLarger && scrollTop > initialSidebarTop) || (!isWindowLarger && scrollTop > initialSidebarTop + heightDelta)) {
sidebar.classList.add('fixed')
} else if (!isScrollingDown && scrollTop <= initialSidebarTop) {
sidebar.classList.remove('fixed')
}
const dragBottomDown = (sidebarBottom <= scrollBottom && isScrollingDown)
const dragTopUp = (sidebarTop >= scrollTop && !isScrollingDown)
if (dragBottomDown) {
if (isWindowLarger) {
sidebar.style.top = 0
} else {
sidebar.style.top = `${-heightDelta}px`
}
} else if (dragTopUp) {
sidebar.style.top = 0
} else if (sidebar.classList.contains('fixed')) {
const currentTop = parseInt(sidebar.style.top, 10)
const minTop = -heightDelta
const scrolledTop = currentTop + scrollDelta
const isPageAtBottom = scrollTop + windowHeight >= document.body.scrollHeight
const newTop = (isPageAtBottom) ? minTop : scrolledTop
sidebar.style.top = `${newTop}px`
}
lastScrollTop = scrollTop
wasScrollingDown = isScrollingDown
})