HTML Table RowSpan: Autofit spanned cells to content

Let’s say you have created an HTML table with following markup:

<table id="xMyTable" style="width:100%;">
   <tr >
      <td style="vertical-align:top">
         <div style="border: 2px solid black; background-color:red; height: 100px;">
         </div>
      </td>
      <td style="vertical-align:top" rowspan="3">
         <div style="border: 2px solid black; background-color:orange; height: 600px">
         </div>
      </td>
   </tr>
   <tr>
      <td style="vertical-align:top">
         <div style="border: 2px solid black; background-color:green; height: 100px">
         </div>
      </td>
   </tr>
   <tr>
      <td style="vertical-align:top">
         <div style="border: 2px solid black; background-color:blue; height: 100px">
         </div>
      </td>
   </tr>
</table>

It’s very basic, one rowspanned cell that holds a content with large height on the right and 3 corresponding cells with content of smaller height on the left. You’d expect it to look like this:

Desired layout of rowspanned HTML table

Unfortunately as is it works only in Google Chrome. In the rest of the browsers, including Interned Explorer and famed FireFox it looks like this:

Current layout of rowspanned HTML table

What happens is browsers automatically spread spanned cells height to evenly fit height of the cell with rowspan. To rectify this situation we need a little help from JavaScript.

First let’s create a function that would adjust height of a cell in relation to total height of the table:

function growCell(td) {
    var table, target, high, low, mid;

    table = td.offsetParent;
    target = table.offsetHeight;
    low = td.offsetHeight;

    // find initial high
    high = low;
    while (table.offsetHeight <= target) {
        high *= 2
        td.style.height = (high) + 'px';
    }

    // binary search!
    while (low + 1 < high) {
        mid = low + Math.floor((high - low) / 2);
        td.style.height = mid + 'px';
        if (table.offsetHeight > target) {
            high = mid;
        } else {
            low = mid;
        }
    }

    td.style.height = low + 'px';
}

Now we need to call this function for every cell in the table starting in reverse from the bottom row:

function growTable(i_sTableID) {
    var xTable = document.getElementById(i_sTableID);

    for (Y = xTable.rows.length - 1; Y >= 0; Y--) {
        for (X = 0; X < xTable.rows[Y].cells.length; X++) {
            growCell(xTable.rows[Y].cells[X])
        }
    }
}

That’s it. Now all we have to do to adjust table layout is call this growTable function and pass ID of the table in question:

growTable('xMyTable');

And the table takes desired layout.


CREDITS: This solution is not mine, I simple translated it from jQuery to plain-vanilla JavaScript. Original method was provided by Jeffery To @stackoverflow.com

Leave a Reply

Your email address will not be published. Required fields are marked *