Improving JavaScript sliding element efficiency

(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 have created a simple JavaScript function to move an element while the user scrolls the page.

(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 seems to work fine, but I have noticed that the browser gets slower as the user continues to scroll. I suspect there may be a memory leak or some other issue, but as I am not a JavaScript expert, I can't pinpoint the problem.

Can anyone provide some insights into this issue?

(tested on Mozilla Firefox 38.0.5)

The stackoverflow snippet does not seem to replicate the problem.

EDIT

Ahmed suggested using the translateY CSS function instead of resetting the "top" property. This change has improved the performance:

(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"; }

    };

})();

Answer №1

Building upon Marcos' response, every time a user scrolls, the element's top is reset and triggers a noticeable repainting process. It is recommended to utilize translate for better performance.

To delve deeper into this topic, check out https://css-tricks.com/tale-of-animation-performance/

Answer №2

When a user resizes or scrolls the page, the onScroll event fires multiple times. To optimize this and prevent excessive firing, consider using a debounce function. One recommended option is the underscore debounce function which you can find here:

http://underscorejs.org/#debounce

Best of luck with your implementation!

UPDATE

I noticed in your code that you are utilizing a for() loop with a limit based on the length of sideBars. What value does this variable reach at its maximum?

Answer №3

Ensure you avoid the repetition of declaring static variables in your loop and apply a Throttling technique to regulate the frequency of function execution:

(function() {    
    var navLinks = document.getElementsByClassName("navLink"),
        limit = 150, 
        margin = 20,
        frequency = 30;//milliseconds interval for throttling (experiment with different values)
    
    window.onscroll = throttle(function(){
        var y = window.pageYOffset,
            n = navLinks.length,
            t = (limit - y >= margin) ? (limit - y) : margin;        
        for(var j=0; j<n; j++) {
            navLinks[j].style.top =  t+"px";
        }
    },frequency);
    
})();


function throttle(func, threshold, scope) {
  threshold || (threshold = 300);
  var prevTime,
      timer;
  return function () {
    var context = scope || this;
    var currentTime = +new Date,
        argumentsList = arguments;
    if (prevTime && currentTime < prevTime + threshold) {
      // keep track
      clearTimeout(timer);
      timer = setTimeout(function () {
        prevTime = currentTime;
        func.apply(context, argumentsList);
      }, threshold);
    } else {
      prevTime = currentTime;
      func.apply(context, argumentsList);
    }
  };
}
html, body {margin:0; padding:0;}
.navLink { position: fixed; top: 150px; width: 300px; background-color: lightblue; }

#navLinkLeft { left: 15px; }
<div id="navLinkLeft" class="navLink">
  <p>Meow.</p>
</div>
<div style="height: 1700px; background-color: pink"></div>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Vue has the ability to automatically escape HTML characters

Take a look at one of the methods I have computed: filtered() { return this.groups.map(group => { return group.replace(this.search, '<span class="has-background-primary">' + this.search + ...

PHP - Truncated html string when appending

I have a situation where I am using PHP to generate HTML for the MPDF library in order to create a PDF file. However, when I include a loop within my PHP-generated HTML, it seems to be cutting off the initial part of the string. Below is the code snippet: ...

Align a span vertically within a div

I need help aligning the content "ABC Company" vertically within a div using Bootstrap 4's alignment helper classes. Despite my efforts, I have not been successful. Here is the code I am using: <div class="container" style="width: 740px;"> < ...

Navigating through images via opacity changes in HTML

Is there a way to create a smooth transition effect between pictures in HTML without reloading the page? I have a series of images that I want users to navigate through by clicking a "Next" button, and I would like each image to fade into the screen. Are ...

The proper application of CSS to dynamically loaded elements in AngularJS is not functioning correctly

I recently discovered a great script from CodyHouse that allows me to create a filterable portfolio. You can check it out here: Using AngularJS, I am able to parse data via JSON seamlessly. However, I have encountered an issue where the CSS is not being a ...

Node.js is hindered by the blocking nature of Mongoose queries

Why does Mongoose block Node.js while fetching data? I always thought it should be non-blocking and return to the callback once data is retrieved. The issue lies in the following code snippet: Container.find({}, function (err, documents) { res.st ...

Adding padding to the top causes the scrollbar to hide at the bottom in Firefox

My HTML page includes the following configured DIV: <div id="contentDiv" style="padding-top: 20px; padding-left: 20px; overflow: auto; height: 100%;" > The content within this DIV is large enough to require a vertical scrollbar. When viewed in IE, ...

Is there a way to access the name of a generic type T class in TypeScript?

I'm currently working on incorporating the Service Locator pattern into my TypeScript project. Below is the snippet of my code: //due to only partial knowledge of TypeScript private static serviceMap: Map<string, any>; public static get& ...

The peculiar actions exhibited by the imported JavaScript file within a Node.js environment

I am currently working on a node app that is quite simple. However, I am facing an issue that I can't seem to resolve. When examining the generated HTML of my express app, it appears as follows: <html style="" class=" js no-touch svg inlinesvg sv ...

What is the process for activating the quasar timepicker once a user has selected a time?

The functionality of the timepicker in Quasar doesn't quite meet my expectations. I don't want to add another library just for this feature. The main issue I have is that it doesn't close automatically after selecting a time. I managed to fi ...

Unusual behavior observed when calculating in Angular

Utilizing Angular.js, I dynamically calculate the height and add the value to the CSS style attribute within an ng-repeat loop. The issue arises with this particular line of code: <div style="height: {{60.0 / 100.0 * (100 - (100.0 / 0.27 * (item.wert ...

In a responsive layout, a floating div refuses to adhere to the left alignment

I am working on a dynamic list using ASP:REPEATER with floating divs aligned to the left. The current layout is as follows: +---------------------+ +---------------------+ +---------------------+ | | | | | ...

Tips for Trimming a Variable in a View with AngularJS

The variable {{bb}} holds the range "9.00 to 10.00" My goal is to show just the value 9 ...

Utilizing Javascript's Mapping Functionality on Arrays

Here is an array that I need help with: var gdpData = {"CA": 1,"US": 2,"BF": 3,"DE": 4}; I am trying to retrieve the value associated with BF using a loop Can anyone provide guidance on how to accomplish this using either JQuery or Javascript? ...

I am looking to expand my CSS/HTML menu with an additional sub-sub menu. What is the correct way to achieve this?

This is my current CSS code that I am working on. I am trying to create a multi-level menu in Blogger with submenus, sub-submenus, and sub-sub-submenus without disrupting the existing formatting. .top-nav { background-color: #f9f9f9; background: t ...

Creating a dynamic hyperlink based on the selections made in three drop-down menus using HTML code

Currently, I am tinkering with HTML code for a website and aiming to create a link on the website based on selections made in three separate drop-down menus. I am seeking HTML code that will direct users to the following URL: ..../[first menu selection ...

A guide to dynamically displaying icons with React and TypeScript based on user-defined properties

Currently, I'm utilizing react-feather for displaying icons within a component. While I can successfully import and display a static icon by manually inserting it, I am faced with the challenge of dynamically rendering an icon based on the value passe ...

What causes jquery to malfunction when making an ajax call?

UPDATE #2: I am experiencing a similar issue to this one, although it is not related to WP: . How can I implement this with my scripts? UPDATE: The main problem arises when the page is initially loaded, everything works smoothly and ajax is not triggered. ...

Tips for achieving full width with Bootstrap

Recently, I delved into the world of bootstrap and encountered some trouble setting my width to 100%. Despite trying to assign width:100%; in my container CSS, it didn't seem to work. The only workaround I found was using container-fluid no-padding in ...

Hide in certain zones, contextual menu

I recently discovered how to create my own context menu with links based on the div clicked (check out here for more details). However, I am facing an issue now. I am struggling to prevent the context menu from appearing above the specific div boxes where ...