简体   繁体   中英

How to set the width of each header cell in a table (with fixed header) to be the same to the biggest in its column, and make the browser respect it?

Here is the infamous table:

在此输入图像描述

My boss wants me, at this time of the year, to make the header of the table fixed, so the user can scroll down the table and continue reading the header. I want to preserve the original precomputed dimensions of the table, I mean, the width that every column has at the moment of its creation (widths aren't established by CSS) and then, adapt the header so its columns match the columns of the body. Following some of the answers I found in Stackoverflow, I started making the header and the body of the table display: block . And after that, I wrote this:

function setTableHeadDimensions() {
    var $taskTable = $('.tablaTareas_PEMVISUALIZA'),
        $firstRow = $taskTable.find('tbody > tr:first-child'),
        $firstRowTds = $firstRow.find('td'),
        $firstRowHead = $taskTable.find('thead > tr:first-child'),
        $secondRowHead = $taskTable.find('thead > tr:eq(1)'),
        $firstRowHeadThs = $firstRowHead.find('th'),
        $secondRowHeadThs = $secondRowHead.find('th'),
        i = 0,
        cells = [];

    //We prepare CSS, so we can specify width.
    $taskTable
        .css('table-layout', 'fixed')
        .find('td, th').each(function () {
            var $tdh = $(this);
            $tdh.css('box-sizing', 'border-box');
            $tdh.css('overflow', 'hidden');
        });

    //Cells of the first row of the table head.
    for (i = 0; i < 3; i++) {
        cells.push($($firstRowHeadThs[i]));
    }

    //Cells of the second row of the table head.
    for (i = 0; i < $secondRowHeadThs.length; i++) {
        cells.push($($secondRowHeadThs[i]));
    }

    //Rest of the cells for the first row.
    for (i = 5; i < $firstRowHeadThs.length; i++) {
        cells.push($($firstRowHeadThs[i]));
    }

    //Try to set the width of the current column's header cell
    //to the biggest cell width in the column.
    for (i = 0; i < cells.length; i++) {
        var maxWidth = 0;

        $taskTable.find('td:nth-child(' + (i + 1) + ')').each(function () {
            var $el = $(this);
            maxWidth = Math.max(maxWidth, $el.width());
        });

        cells[i].width(maxWidth);
    }
}

But, as you can see in the picture, the browser doesn't want to cooperate. What's more, it establishes the width of the cell, but to a number that doesn't match the width of it's corresponding column:

在此输入图像描述

What's more, it doesn't match the width of the row it should match:

在此输入图像描述

So I have two questions:

  1. Why does the browser behave in the way it does?
  2. How can I solve this problem in a way compatible with IE8? (no fancy CSS3 solution, please)

Here's a codepen with the example cut down to the minimum necessary: Codepen example

I solved it. In reality, there were two problems:

The first one is that jQuery.width() returns only the width of the content of the cell, without padding and margin (even if you specify border-sizing: border-box ). I found more natural to use jQuery.css('width') and then take borders and padding into account in my calculations, without specifying border-sizing: border-box because retrieving the width with border-sizing: border-box and then setting it in another element with the idea of matching both widths can be error prone (I had problems with it).

The second one is if you use rowspan in the header of the table. In that case, you have to establish the width of the rows envolved doing the proper calculations, not only one of them hopping that the rest of the rows will adapt.

Here's the codepen with the solution: http://codepen.io/PolarKuma/pen/BQXMbO

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM