Reputation: 613
(function() {
window.onscroll = function () {
var sideBars = document.getElementsByClassName("sideBar");
var y = window.pageYOffset;
var threshold = 200;
var marge = 15;
if(threshold - y >= marge) {
for(var i=0; i<sideBars.length; i++) { sideBars[i].style = "top: " + (threshold - y) + "px ;"; }
} else {
for(var i=0; i<sideBars.length; i++) { sideBars[i].style = "top: " + marge + "px ;"; }
}
};
})();
.sideBar { position: fixed; top: 200px; width: 300px; background-color: lightgreen; }
#sideBarLeft { left: 10px; }
<div id="sideBarLeft" class="sideBar">
<p>Quack.</p>
</div>
<div style="height: 1800px; background-color: yellow"></div>
I made a small function to slide an element as the user scroll the page in pure Javascript.
(function() {
window.onscroll = function () {
var sideBars = document.getElementsByClassName("sideBar");
var y = window.pageYOffset;
var threshold = 200;
var marge = 15;
if(threshold - y >= marge) {
for(var i=0; i<sideBars.length; i++) { sideBars[i].style = "top: " + (threshold - y) + "px ;"; }
} else {
for(var i=0; i<sideBars.length; i++) { sideBars[i].style = "top: " + marge + "px ;"; }
}
};
})();
It perfectly works, but the browser seems to become slower and slower as the user scroll the page. I suspect there is a memory leak somewhere or something wrong but I can't figure what since I am quite not a JS expert
Can some of you enlighten me with this issue ?
(tried with mozilla firefox 38.0.5)
The stackoverflow snippet semms to not reproduce the problem.
EDIT
Ahmed suggested to use translateY CSS function instead of resetting the "top" property. This way, it works like a charm :
(function() {
window.onscroll = function () {
var sideBars = document.getElementsByClassName("sideBar");
var y = window.pageYOffset;
var origin = 200;
var marge = 15;
var offset = origin-y >= marge ? -y : marge-origin;
for(var i=0; i<sideBars.length; i++) { sideBars[i].style.transform = "translateY(" + offset + "px"; }
};
})();
Upvotes: 1
Views: 67
Reputation: 525
In addition to Marcos answer, every time user scrolls, the top
is reset and a heavy paint occur. You should use translate
.
You can read more here https://css-tricks.com/tale-of-animation-performance/
Upvotes: 1
Reputation: 16184
Avoid redeclaring static variables within your loop and Throttle your function to only run every n milliseconds:
(function() {
var sideBars = document.getElementsByClassName("sideBar"),
threshold = 200,
marge = 15,
freq = 25;//millisecond frequency for throttle (try increasing this to see it working)
window.onscroll = throttle(function(){
var y = window.pageYOffset,
l = sideBars.length,
t = (threshold - y >= marge) ? (threshold - y) : marge;
for(var i=0; i<l; i++) {
sideBars[i].style.top = t+"px";
}
},freq);
})();
function throttle(fn, threshhold, scope) {
threshhold || (threshhold = 250);
var last,
deferTimer;
return function () {
var context = scope || this;
var now = +new Date,
args = arguments;
if (last && now < last + threshhold) {
// hold on to it
clearTimeout(deferTimer);
deferTimer = setTimeout(function () {
last = now;
fn.apply(context, args);
}, threshhold);
} else {
last = now;
fn.apply(context, args);
}
};
}
html, body {margin:0; padding:0;}
.sideBar { position: fixed; top: 200px; width: 300px; background-color: lightgreen; }
#sideBarLeft { left: 10px; }
<div id="sideBarLeft" class="sideBar">
<p>Quack.</p>
</div>
<div style="height: 1800px; background-color: yellow"></div>
Upvotes: 0
Reputation: 22158
The onScroll event fires tons of times when a user resize or scroll the page. You can add a deboucer to the function, is a lot of them, but I recommend you to use the underscore debounce function:
http://underscorejs.org/#debounce
Good luck
I see your code again and you use for() with the limit of sideBars length . What is the maximum number of this variable?
Upvotes: 0