JavaScript may experience delays when setting the height

Two html tables I have, filled with various elements like span, input, select, and more. My goal is to make sure that the rows in both tables are of equal height. Unfortunately, simply setting the 'height' attribute on tr or td did not yield the desired results, as a row would adjust its height based on the tallest element within it.

Unable to find a CSS solution for enforcing row heights, I resorted to writing a JavaScript function. This function loops through each row, compares the heights of the corresponding rows in the two tables, and adjusts the height to match the taller row.

However, this method proved to be slow when dealing with tables containing numerous rows. It seems that the performance lag is caused by the reflow triggered by styling changes.

Is there any advice on how to improve this? Keep in mind that merging the tables is not an option.

Below is a snippet of my code, but I am open to suggestions for a completely different approach:

var rightTableRows = mainTable.children("tbody").children("tr:parent");
var leftTableRows = colHeader.children("tbody").children("tr:parent");

for (chr=0;chr < leftTableRows .length;chr++) {
    var rowLeft = leftTableRows [chr];
    var heightleft = rowLeft.offsetHeight;
    var rowRight = rightTableRows[chr];
    var heightright = rowRight.offsetHeight;
    if(heightleft != heightright){
            console.log("left: "+heightleft +" - right: "+heightright);
        if(heightleft>heightright){
           rowRight.setAttribute("style","height:"+heightleft+"px");
        }else{
           rowLeft.setAttribute("style","height:"+heightright+"px");
        }
    }

}

Answer №1

If you find yourself repeatedly reading and writing to the DOM, it can significantly impact performance. A better approach is to first gather all the information you need (reads) and then make the necessary changes (writes). This prevents unnecessary reflows and calculations in between. Consider using two separate loops: one to determine the correct heights and another to apply them:

var rightTableRows = mainTable.children("tbody").children("tr:parent");
var leftTableRows = colHeader.children("tbody").children("tr:parent");
var length = leftTableRows.length;
var heights = [];

for (var chr = 0; chr < length; chr++) {
    var rowLeft = leftTableRows[chr];
    var heightleft = rowLeft.offsetHeight;
    var rowRight = rightTableRows[chr];
    var heightright = rowRight.offsetHeight;

    if (heightleft > heightright) {
        heights.push({
            elem: rowRight,
            height: heightleft
        });
    } else {
        heights.push({
            elem: rowLeft,
            height: heightright
        });
    }
}

for (var i = 0; i < heights.length; i++) {
    heights[i].elem.style.height = heights[i].height + 'px';
}

By storing elements and their new heights as objects in an array, you only access the DOM once. Other optimizations include eliminating unnecessary if() statement, caching the HTML nodelist length, and directly setting style.height instead of using setAttribute() which is slower.

Answer №2

If you're unsure about the maximum height of your cells, consider converting your tables into divs and utilizing display flex.

This approach will give you the desired functionality but will require restructuring the HTML layout.

Instead of placing elements from both tables in a sequential order, you'll need to alternate between them.

Answer №3

Here's a snippet from a helpful response written by jfriend00. Don't forget to show your appreciation with an upvote!

Optimizing DOM Manipulations

  1. Reflows are queued. ....
  2. Requesting certain properties can trigger an immediate reflow. Some DOM properties require accurate layout information, which may prompt the browser to relayout synchronously if there is pending layout from a previous modification. To avoid this, ensure you request all necessary properties before making any changes to the DOM.

  3. Batch up all your DOM changes at once. It's best practice to make all pending DOM changes together in one synchronous batch of Javascript code. This allows the browser to queue the reflow and repaint actions and perform them only once after all DOM changes have been made. For further efficiency, combine modifications to the same element to process it only once with the final value instead of each change separately.

  4. DOM modifications can sometimes be optimized. ....


Points 2 and 3 are crucial - fetching offsetHeight for each row and setting new values individually can lead to unnecessary reflows. Instead, read all rows first, store pending changes in memory, and apply new heights in a separate loop using the saved values.

Answer №4

Uncertain of the exact reason for this issue, however:

By adjusting the line-height style of the td element, you can potentially increase the height of the td itself and in turn affect the height of the tr element. If this doesn't work as expected, consider wrapping the content of the td within a div and applying the line-height to that instead.

An alternative approach, for efficiency, is to assign the same style class to all relevant elements. Then, once the heights have been calculated, set the line-height for the class to modify the height of all associated elements. Exploring Javascript's styleSheet object will provide further insight into how to accomplish this....

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

Tips for holding off until the fetch operation is complete

Recently started working with JavaScript and facing an issue where the return part doesn't wait for my status from the fetch call. How can I delay this until the status is retrieved? Even tried adding timeouts but that didn't solve the problem. c ...

A step-by-step guide on bringing in objects in JavaScript and Node.js

Let's say we have a file called main2.js exports.obj = { x: 10, setX: function(y) { this.x = y; }, getX: function() { return this.x; } }; Now, we also have two other files: abc.js const obj = require("./main2").o ...

Display a div using JavaScript when the mouse moves and make it follow the cursor

In my application, I have a set of customer records displayed as rows in a table. I am looking to implement a feature where, upon hovering over a record (row), a div will pop up showing more detailed information about that specific record. This hover-over ...

gap between the main content and the anchored bottom navigation

Working on a homepage using Bootstrap 4 with a navigation bar fixed to the bottom and a carousel above it. It looks good on desktop/tablet, but facing issues on mobile views. There's an unwanted white space between the carousel and the navigation on ...

How to apply dynamic styling to a MatHeaderCell using NgStyle?

My goal is to dynamically style a MatHeaderCell instance using the following code: [ngStyle]="styleHeaderCell(c)" Check out my demo here. After examining, I noticed that: styleHeaderCell(c) It receives the column and returns an object, however ...

I am perplexed by the CSS property `height: auto;` which seems to be making the element taller than necessary. How exactly is

Currently, I am dealing with some HTML/CSS aspects of an already established WordPress website. It appears that there might be an issue related to the theme's CSS causing this problem, although it is not immediately apparent. Specifically, there is s ...

Is there a way to use Selenium to automate the clicking of two buttons with empty href attributes? Each button has a function name and arguments within the href

Here is the HTML code for both buttons: <td> <a href="javascript:abcMy(2310);" class="btn btn-lawa btn-primary btn-primary-lawa">View</a> </td> <td> <a href="javascript:abcMy(2330);" class="btn btn-lawa btn-primary btn ...

Is there a way for me to receive numerical values instead of NaN?

I'm currently facing a challenge in creating a Fibonacci number generator and I've hit a roadblock. It seems like I have a solution, but the appearance of NaN's is causing me some trouble. function fibonacciGenerator (n) { var output = [ ...

Node.js Express.js Module for Asynchronous SqLite Operations

Currently, I am working on a task that involves making synchronous requests to a database and passing the data to Express. Here is the code snippet: app.get('/', (req, res) => { let db = new sqlite3.Database('./Problems.db'); ...

Creating Images that appear optimized on smaller screens - the art of responsive design!

Currently, I am in the process of working on this test page located at the following link: While the page appears fine on my laptop screen, it is displaying poorly on my phone's browser. The images, in particular, appear disorganized and messy. Coul ...

Encountering an issue with a <a> tag containing a <div> element with two columns

After coding this with a global tag <a>, I encountered an issue where the link ID was defined and appeared at the bottom wherever my mouse hovered. <a class="link" href="opencl/toto.htm"> <div class=&quo ...

Not another instance of the elusive 'Unrecognized provider' error in an AngularJS service

I hate to be the one asking for help, but I've been stuck on this issue for quite some time now. Within my AngularJS application, I have three files that just won't work together. Despite trying various solutions both online and within the projec ...

Unraveling the enigmatic duality of self-closure with Bootstrap 4

In the small div element, I need to incorporate multiple tooltip functionalities. Furthermore, as this div has an "overflow: auto" attribute, Popper.js automatically ensures that the tooltips remain within the boundaries of the element. In such situation ...

Complete the form submission and transfer the data to ajax on a separate page

I'm working on a project where I have a form on page1.php that redirects to page2.php. My goal is to pass the data from the form to page3.php automatically when page2.php loads, without the user needing to see anything happening in page3. What would ...

Seeking help on modfiying div content with AJAX - any tips for showing navigation using hash or anchor?

Looking to create a dynamic page that updates content within a div asynchronously while also providing users with direct access to specific content within the div by using anchors (e.g. www.website.co.uk/#page1). I've successfully implemented the upd ...

Issues with HTML Email display

Hey there, I am facing an issue while trying to send an HTML email. I am aware that Outlook does not support a lot of CSS formatting, but I can't figure out why this simple setup is breaking. Is there a quick fix or alternative solution? Take a look a ...

Insert a THREE.Points element into the scene: Error in THREE.Object3D.add: The object being added is not a valid instance of THREE.Object3D (

Trying to incorporate a system of particles, a THREE.Points element into the scene has resulted in the following error: "THREE.Object3D.add: object not an instance of THREE.Object3D. undefined" The code used for this is as follows: var backCount = 1800; ...

Creating a JSON array in JavaScript: A step-by-step guide

Presently, I am engrossed in a project involving the creation of a Box and Whisker Plot. The data for this task is being sourced from a PHP file and then passed on to a JavaScript function for the actual Box and Whisker Plot generation. In my possession, t ...

Display the intersection of two objects in varying colors using three.js

Is there a way to display the overlapping volume of two objects in THREE.js using different colors or textures? I want to be able to show the combination of the two objects with a unique color, like purple for example if the original colors are red and blu ...

Tips for importing a JavaScript file from a URL and initializing a class in a React component

I am looking to incorporate the PitchPrint app into a React website. They offer a tutorial for vanilla HTML/JS integration here. Following their instructions, I included script tags with links to jQuery and their app file in my index.html file. I then crea ...