admin管理员组文章数量:1024592
I'm trying to achieve what is outlined in this Stack Overflow question, without jQuery dependency: stackoverflow/questions/18358816/sticky-sidebar-stick-to-bottom-when-scrolling-down-top-when-scrolling-up
But I didn't want to hijack that question.
Basically, I want the content in the sidebar to be independently scrollable but fixed when the viewport reaches either end of the sidebars contents on scroll.
My main stumbling block appears to not being able to calculate the elementTop
variable when the sidebar is absolutely positioned and between the top and bottom of the container which I have set to be full height.
Full code below:
var StickySidebar = function(eventie) {
var container, containerTop, containerHeight, // container
element, elementTop, elementHeight, elStyle, // element
viewportTop = -1, viewportHeight, documentTop, // viewport
lastViewportTop, scrollingDown, top = false , bottom = false,// sticky vars
scroll = window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.msRequestAnimationFrame ||
window.oRequestAnimationFrame ||
function(callback){ window.setTimeout(callback, 1000/60); },
options = {
container : document.querySelector('.sidebar-container'),
element : document.querySelector('.sidebar'),
sidebarClass : 'sidebar',
bottomOffset : -15,
topOffset: 90,
},
_updateValue = function() {
viewportHeight = window.innerHeight;
},
_offset = function(obj) {
var ol = ot = 0;
if (obj.offsetParent) {
do {
ol += obj.offsetLeft;
ot += obj.offsetTop;
} while (obj = obj.offsetParent);
}
return {
left: ol,
top: ot
};
},
init = function(){
if(options.element !== null) {
container = options.container;
containerTop = offset(container).top;
containerHeight = container.clientHeight;
element = options.element;
elementTop = offset(element).top;
elementHeight = options.element.clientHeight;
lastViewportTop = window.scrollY;
viewportHeight = window.innerHeight;
eventie.bind(document, "scroll", _loop);
eventie.bind(window, "resize", _updateValue);
}
},
_loop = function() {
if (viewportTop == window.pageYOffset) {
scroll(_loop);
return false;
} else viewportTop = window.pageYOffset;
_updateValue();
var viewportBottom, elementTooBig, topOffset;
elementTop = offset(element).top;
elementHeight = element.clientHeight;
containerHeight = container.clientHeight;
scrollingDown = viewportTop > lastViewportTop;
elementTooBig = elementHeight > viewportHeight;
console.log("elementTop : " + elementTop);
console.log("viewportTop : " + viewportTop);
if (scrollingDown) {
if (viewportTop + viewportHeight >= elementTop + elementHeight) {
element.setAttribute('style','position:fixed; bottom:30px;');
} else {
element.setAttribute('style','position:absolute; top:'+ elementTop +'px;'); // issue 1
}
if (viewportTop + viewportHeight > containerTop + containerHeight) {
element.setAttribute('style','position:absolute; bottom:0;');
}
} else {
if (viewportTop < containerTop - 60) {
element.removeAttribute('style');
return;
}
if (viewportTop <= elementTop) {
element.setAttribute('style','position:fixed; top:90px;');
} else {
element.setAttribute('style','position:absolute; top:'+ elementTop +'px;');
elementTop = viewportTop + elementTop;
}
}
lastViewportTop = viewportTop;
};
return {
init: init
};
}(eventie);
I've been trying to tackle this issue for a few weeks now, and it has been driving me insane. Any help would be greatly appreciated.
I'm trying to achieve what is outlined in this Stack Overflow question, without jQuery dependency: stackoverflow./questions/18358816/sticky-sidebar-stick-to-bottom-when-scrolling-down-top-when-scrolling-up
But I didn't want to hijack that question.
Basically, I want the content in the sidebar to be independently scrollable but fixed when the viewport reaches either end of the sidebars contents on scroll.
My main stumbling block appears to not being able to calculate the elementTop
variable when the sidebar is absolutely positioned and between the top and bottom of the container which I have set to be full height.
Full code below:
var StickySidebar = function(eventie) {
var container, containerTop, containerHeight, // container
element, elementTop, elementHeight, elStyle, // element
viewportTop = -1, viewportHeight, documentTop, // viewport
lastViewportTop, scrollingDown, top = false , bottom = false,// sticky vars
scroll = window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.msRequestAnimationFrame ||
window.oRequestAnimationFrame ||
function(callback){ window.setTimeout(callback, 1000/60); },
options = {
container : document.querySelector('.sidebar-container'),
element : document.querySelector('.sidebar'),
sidebarClass : 'sidebar',
bottomOffset : -15,
topOffset: 90,
},
_updateValue = function() {
viewportHeight = window.innerHeight;
},
_offset = function(obj) {
var ol = ot = 0;
if (obj.offsetParent) {
do {
ol += obj.offsetLeft;
ot += obj.offsetTop;
} while (obj = obj.offsetParent);
}
return {
left: ol,
top: ot
};
},
init = function(){
if(options.element !== null) {
container = options.container;
containerTop = offset(container).top;
containerHeight = container.clientHeight;
element = options.element;
elementTop = offset(element).top;
elementHeight = options.element.clientHeight;
lastViewportTop = window.scrollY;
viewportHeight = window.innerHeight;
eventie.bind(document, "scroll", _loop);
eventie.bind(window, "resize", _updateValue);
}
},
_loop = function() {
if (viewportTop == window.pageYOffset) {
scroll(_loop);
return false;
} else viewportTop = window.pageYOffset;
_updateValue();
var viewportBottom, elementTooBig, topOffset;
elementTop = offset(element).top;
elementHeight = element.clientHeight;
containerHeight = container.clientHeight;
scrollingDown = viewportTop > lastViewportTop;
elementTooBig = elementHeight > viewportHeight;
console.log("elementTop : " + elementTop);
console.log("viewportTop : " + viewportTop);
if (scrollingDown) {
if (viewportTop + viewportHeight >= elementTop + elementHeight) {
element.setAttribute('style','position:fixed; bottom:30px;');
} else {
element.setAttribute('style','position:absolute; top:'+ elementTop +'px;'); // issue 1
}
if (viewportTop + viewportHeight > containerTop + containerHeight) {
element.setAttribute('style','position:absolute; bottom:0;');
}
} else {
if (viewportTop < containerTop - 60) {
element.removeAttribute('style');
return;
}
if (viewportTop <= elementTop) {
element.setAttribute('style','position:fixed; top:90px;');
} else {
element.setAttribute('style','position:absolute; top:'+ elementTop +'px;');
elementTop = viewportTop + elementTop;
}
}
lastViewportTop = viewportTop;
};
return {
init: init
};
}(eventie);
I've been trying to tackle this issue for a few weeks now, and it has been driving me insane. Any help would be greatly appreciated.
Share Improve this question edited May 23, 2017 at 11:33 CommunityBot 11 silver badge asked Dec 11, 2015 at 0:36 Seán O'GradySeán O'Grady 3631 gold badge6 silver badges19 bronze badges 4-
You can just use css with
position: fixed;
to solve this. And you can use responsive design for small screen. So no JS is needed. – nloomans Commented Dec 13, 2015 at 12:39 - Thanks for the response but that will not work. Not trying to be rude, but I don't think you understand the question fully. – Seán O'Grady Commented Dec 13, 2015 at 15:04
- 1 Are you translating this answer to pure JS? – approxiblue Commented Dec 13, 2015 at 21:21
- I have tried that already but he is using css transform instead of switching fixed positioning on and off. It worked but the performance was suboptimal. – Seán O'Grady Commented Dec 13, 2015 at 21:38
1 Answer
Reset to default 5 +50If you're just trying to achieve the desired result not necessarily creating that yourself - well, there are many JavaScript libraries that provide that.
For example, Stickyfill is actually a polyfill for position: sticky
which is natively supported only in Firefox 41+ and Safari 8+. Here is the demo with all kinds of stickiness you can imagine :)
P.S. At first glance you might notice something about jQuery there, but it's pure JavaScript and just adds a jQuery extension.
I'm trying to achieve what is outlined in this Stack Overflow question, without jQuery dependency: stackoverflow/questions/18358816/sticky-sidebar-stick-to-bottom-when-scrolling-down-top-when-scrolling-up
But I didn't want to hijack that question.
Basically, I want the content in the sidebar to be independently scrollable but fixed when the viewport reaches either end of the sidebars contents on scroll.
My main stumbling block appears to not being able to calculate the elementTop
variable when the sidebar is absolutely positioned and between the top and bottom of the container which I have set to be full height.
Full code below:
var StickySidebar = function(eventie) {
var container, containerTop, containerHeight, // container
element, elementTop, elementHeight, elStyle, // element
viewportTop = -1, viewportHeight, documentTop, // viewport
lastViewportTop, scrollingDown, top = false , bottom = false,// sticky vars
scroll = window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.msRequestAnimationFrame ||
window.oRequestAnimationFrame ||
function(callback){ window.setTimeout(callback, 1000/60); },
options = {
container : document.querySelector('.sidebar-container'),
element : document.querySelector('.sidebar'),
sidebarClass : 'sidebar',
bottomOffset : -15,
topOffset: 90,
},
_updateValue = function() {
viewportHeight = window.innerHeight;
},
_offset = function(obj) {
var ol = ot = 0;
if (obj.offsetParent) {
do {
ol += obj.offsetLeft;
ot += obj.offsetTop;
} while (obj = obj.offsetParent);
}
return {
left: ol,
top: ot
};
},
init = function(){
if(options.element !== null) {
container = options.container;
containerTop = offset(container).top;
containerHeight = container.clientHeight;
element = options.element;
elementTop = offset(element).top;
elementHeight = options.element.clientHeight;
lastViewportTop = window.scrollY;
viewportHeight = window.innerHeight;
eventie.bind(document, "scroll", _loop);
eventie.bind(window, "resize", _updateValue);
}
},
_loop = function() {
if (viewportTop == window.pageYOffset) {
scroll(_loop);
return false;
} else viewportTop = window.pageYOffset;
_updateValue();
var viewportBottom, elementTooBig, topOffset;
elementTop = offset(element).top;
elementHeight = element.clientHeight;
containerHeight = container.clientHeight;
scrollingDown = viewportTop > lastViewportTop;
elementTooBig = elementHeight > viewportHeight;
console.log("elementTop : " + elementTop);
console.log("viewportTop : " + viewportTop);
if (scrollingDown) {
if (viewportTop + viewportHeight >= elementTop + elementHeight) {
element.setAttribute('style','position:fixed; bottom:30px;');
} else {
element.setAttribute('style','position:absolute; top:'+ elementTop +'px;'); // issue 1
}
if (viewportTop + viewportHeight > containerTop + containerHeight) {
element.setAttribute('style','position:absolute; bottom:0;');
}
} else {
if (viewportTop < containerTop - 60) {
element.removeAttribute('style');
return;
}
if (viewportTop <= elementTop) {
element.setAttribute('style','position:fixed; top:90px;');
} else {
element.setAttribute('style','position:absolute; top:'+ elementTop +'px;');
elementTop = viewportTop + elementTop;
}
}
lastViewportTop = viewportTop;
};
return {
init: init
};
}(eventie);
I've been trying to tackle this issue for a few weeks now, and it has been driving me insane. Any help would be greatly appreciated.
I'm trying to achieve what is outlined in this Stack Overflow question, without jQuery dependency: stackoverflow./questions/18358816/sticky-sidebar-stick-to-bottom-when-scrolling-down-top-when-scrolling-up
But I didn't want to hijack that question.
Basically, I want the content in the sidebar to be independently scrollable but fixed when the viewport reaches either end of the sidebars contents on scroll.
My main stumbling block appears to not being able to calculate the elementTop
variable when the sidebar is absolutely positioned and between the top and bottom of the container which I have set to be full height.
Full code below:
var StickySidebar = function(eventie) {
var container, containerTop, containerHeight, // container
element, elementTop, elementHeight, elStyle, // element
viewportTop = -1, viewportHeight, documentTop, // viewport
lastViewportTop, scrollingDown, top = false , bottom = false,// sticky vars
scroll = window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.msRequestAnimationFrame ||
window.oRequestAnimationFrame ||
function(callback){ window.setTimeout(callback, 1000/60); },
options = {
container : document.querySelector('.sidebar-container'),
element : document.querySelector('.sidebar'),
sidebarClass : 'sidebar',
bottomOffset : -15,
topOffset: 90,
},
_updateValue = function() {
viewportHeight = window.innerHeight;
},
_offset = function(obj) {
var ol = ot = 0;
if (obj.offsetParent) {
do {
ol += obj.offsetLeft;
ot += obj.offsetTop;
} while (obj = obj.offsetParent);
}
return {
left: ol,
top: ot
};
},
init = function(){
if(options.element !== null) {
container = options.container;
containerTop = offset(container).top;
containerHeight = container.clientHeight;
element = options.element;
elementTop = offset(element).top;
elementHeight = options.element.clientHeight;
lastViewportTop = window.scrollY;
viewportHeight = window.innerHeight;
eventie.bind(document, "scroll", _loop);
eventie.bind(window, "resize", _updateValue);
}
},
_loop = function() {
if (viewportTop == window.pageYOffset) {
scroll(_loop);
return false;
} else viewportTop = window.pageYOffset;
_updateValue();
var viewportBottom, elementTooBig, topOffset;
elementTop = offset(element).top;
elementHeight = element.clientHeight;
containerHeight = container.clientHeight;
scrollingDown = viewportTop > lastViewportTop;
elementTooBig = elementHeight > viewportHeight;
console.log("elementTop : " + elementTop);
console.log("viewportTop : " + viewportTop);
if (scrollingDown) {
if (viewportTop + viewportHeight >= elementTop + elementHeight) {
element.setAttribute('style','position:fixed; bottom:30px;');
} else {
element.setAttribute('style','position:absolute; top:'+ elementTop +'px;'); // issue 1
}
if (viewportTop + viewportHeight > containerTop + containerHeight) {
element.setAttribute('style','position:absolute; bottom:0;');
}
} else {
if (viewportTop < containerTop - 60) {
element.removeAttribute('style');
return;
}
if (viewportTop <= elementTop) {
element.setAttribute('style','position:fixed; top:90px;');
} else {
element.setAttribute('style','position:absolute; top:'+ elementTop +'px;');
elementTop = viewportTop + elementTop;
}
}
lastViewportTop = viewportTop;
};
return {
init: init
};
}(eventie);
I've been trying to tackle this issue for a few weeks now, and it has been driving me insane. Any help would be greatly appreciated.
Share Improve this question edited May 23, 2017 at 11:33 CommunityBot 11 silver badge asked Dec 11, 2015 at 0:36 Seán O'GradySeán O'Grady 3631 gold badge6 silver badges19 bronze badges 4-
You can just use css with
position: fixed;
to solve this. And you can use responsive design for small screen. So no JS is needed. – nloomans Commented Dec 13, 2015 at 12:39 - Thanks for the response but that will not work. Not trying to be rude, but I don't think you understand the question fully. – Seán O'Grady Commented Dec 13, 2015 at 15:04
- 1 Are you translating this answer to pure JS? – approxiblue Commented Dec 13, 2015 at 21:21
- I have tried that already but he is using css transform instead of switching fixed positioning on and off. It worked but the performance was suboptimal. – Seán O'Grady Commented Dec 13, 2015 at 21:38
1 Answer
Reset to default 5 +50If you're just trying to achieve the desired result not necessarily creating that yourself - well, there are many JavaScript libraries that provide that.
For example, Stickyfill is actually a polyfill for position: sticky
which is natively supported only in Firefox 41+ and Safari 8+. Here is the demo with all kinds of stickiness you can imagine :)
P.S. At first glance you might notice something about jQuery there, but it's pure JavaScript and just adds a jQuery extension.
本文标签: javascriptFreeScrolling Sticky Sidebar Without jQueryStack Overflow
版权声明:本文标题:javascript - Free-Scrolling Sticky Sidebar Without jQuery - Stack Overflow 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://it.en369.cn/questions/1745608345a2158857.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论