views:

72

answers:

3

I have the following problem:

I have to list several items each with several properties on a web page. The listing is done in two HTML tables. One table for the headers and one table for the items. This separation is needed in order to have possibility to scroll only through the list. (It would be odd to have a scrollbar in the header section). AFAIK there is only one way to do scrolling in a list in HTML is the div overflow property.

The problem is that I need to set the width of columns ( elements) in the whole listing i.e. in header and in the elements list. Here is a simplified example of how it is done now:

<table width="98%">
    <tr> 
        <td>1</td> <td>2</td> <td>3</td> <td>4</td>
    </tr>
    <div style="width: 100%; height: 300px; overflow-y:scroll">
        <table>
            <tr> 
                <td>123456789101112</td> <td>2</td> <td>3</td> <td>4</td>
            </tr>
        </table>
    </div>
</table>

The problem is that since the elements in the list may have long (I mean many characters) values the browsers expand the cells even if width attribute is used. Since the header is in a separate its columns will have a different length then the columns of the div's .

So far I have tried to let the browser render the columns in the list and then get those computed styles and apply them to the header's columns but it seems that the header columns do not get exactly that widths. I have had the same problem in other places in the project, but since there the text widths were the constant I used pixels for the widths, different lengths in FF and in IE8, but now the problem is - I think- even more complex.

How can I make the columns have the same width in both tables?

+2  A: 

Your example is invalid HTML. I wouldn't recommend using that way at all.

The only way to make all the columns have the same width (without the help of JavaScript) is in fact having them in the same table.

Check out this question. I haven't tested them, but some of the answers look like they provide the functionality you need using only one table element using thead and tbody elements.

Pekka
@Pekka: I am currently checking the possible solutions discussed in the question you provided.
Atticus
@Pekka: Finally I have chosen Mark Malek's jQuery plugin. Thanks for pointing out that question.
Atticus
A: 

I haven't tested it a lot but this appears to work:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"&gt;
<html>
<head><title></title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<style type="text/css"><!--
tbody{
    width: 100%;
    height: 300px;
    overflow-y:scroll;
}
--></style>
</head>
<body>

<table width="98%">
<thead>
<tr> 
    <td>1</td> <td>2</td> <td>3</td> <td>4</td>
</tr>
</thead>
<tbody>
    <tr> 
        <td>123456789101112</td> <td>2</td> <td>3</td> <td>4</td>
    </tr>
    <tr> 
        <td>123456789101112</td> <td>2</td> <td>3</td> <td>4</td>
    </tr>
    <tr> 
        <td>123456789101112</td> <td>2</td> <td>3</td> <td>4</td>
    </tr>
    <tr> 
        <td>123456789101112</td> <td>2</td> <td>3</td> <td>4</td>
    </tr>
    <tr> 
        <td>123456789101112</td> <td>2</td> <td>3</td> <td>4</td>
    </tr>
    <tr> 
        <td>123456789101112</td> <td>2</td> <td>3</td> <td>4</td>
    </tr>
    <tr> 
        <td>123456789101112</td> <td>2</td> <td>3</td> <td>4</td>
    </tr>
    <tr> 
        <td>123456789101112</td> <td>2</td> <td>3</td> <td>4</td>
    </tr>
    <tr> 
        <td>123456789101112</td> <td>2</td> <td>3</td> <td>4</td>
    </tr>
    <tr> 
        <td>123456789101112</td> <td>2</td> <td>3</td> <td>4</td>
    </tr>
    <tr> 
        <td>123456789101112</td> <td>2</td> <td>3</td> <td>4</td>
    </tr>
    <tr> 
        <td>123456789101112</td> <td>2</td> <td>3</td> <td>4</td>
    </tr>
    <tr> 
        <td>123456789101112</td> <td>2</td> <td>3</td> <td>4</td>
    </tr>
    <tr> 
        <td>123456789101112</td> <td>2</td> <td>3</td> <td>4</td>
    </tr>
    <tr> 
        <td>123456789101112</td> <td>2</td> <td>3</td> <td>4</td>
    </tr>
    <tr> 
        <td>123456789101112</td> <td>2</td> <td>3</td> <td>4</td>
    </tr>
    <tr> 
        <td>123456789101112</td> <td>2</td> <td>3</td> <td>4</td>
    </tr>
    <tr> 
        <td>123456789101112</td> <td>2</td> <td>3</td> <td>4</td>
    </tr>
    <tr> 
        <td>123456789101112</td> <td>2</td> <td>3</td> <td>4</td>
    </tr>
    <tr> 
        <td>123456789101112</td> <td>2</td> <td>3</td> <td>4</td>
    </tr>
</table>

</body>
</html>

Update: It only seems to work in Firefox.

Álvaro G. Vicario
@Álvaro G. Vicario: Nice example. However it does not work in IE8. I do not know what is the problem, but id I could fix it this would be a nice and easy solution.
Atticus
@Álvaro G. Vicario: The problem is that for some reason the height property is not set in IE8. One other thing is that I can not use Doctypes.
Atticus
@Atticus: If you cannot use Doctypes, you're practically lost: without a Doctype triggering (Almost) Standards mode you'll have to deal with many different quirks the browser manufacturers implemented. It's hardly possibly to get a decent rendering in every browser (especially in IE).
Marcel Korpel
@Marcel Korpel: I do not really know why are we not using Doctypes, I have not tried, what I have heard is that it is because of the Turbine framework we are using. Anyway AFAIK Doctype is important for search engines and our project is for internal use.
Atticus
@Atticus: No, Doctype isn't important for search engines, it lets the browser choose its rendering mode. See http://hsivonen.iki.fi/doctype/
Marcel Korpel
@Atticus, when I said that I hadn't tested it a lot I actually meant "works for me in Firefox". It appears that other browsers do not support rendering `<tbody>` elements the way we need. It's a pitty that the simple trick did not work but that's life :)
Álvaro G. Vicario
@Marcel Korpel: We do not use Doctypes because we had some problems (don't know exactly what) with our template rendering engine - Apache Velocity - when using Doctypes. Probably it is not an issue anymore, so we should consider using them.
Atticus
A: 

The following example uses JavaScript to set the width of header cells:

<head>
    <style>
        #headerTable {
            background-color: #a0f0a0;
            font-size: 18px;
            font-weight: bold;
        }

        #headerTable td {
            text-align: center;
        }

        #itemsDiv {
            height: 300px; 
            overflow:auto
        }

        #itemsTable {
            background-color: #e0e0b0;
            font-size: 14px;
        }

        #itemsTable td {
            padding: 5px;
            text-align: right;
        }
    </style>
    <script>
        function ResizeHeaderTable () {
            var headerTable = document.getElementById ("headerTable");
            var itemsTable = document.getElementById ("itemsTable");
                // resize header cells
            if (headerTable.rows.length > 0 && itemsTable.rows.length > 0) {
                var firstHeaderRow = headerTable.rows[0];
                var firstItemsRow = itemsTable.rows[0];
                var colsNum = Math.min (firstHeaderRow.cells.length, firstItemsRow.cells.length);
                for (var i = 0; i < colsNum; i++) {
                    var cellWidth = firstItemsRow.cells[i].offsetWidth;
                    firstHeaderRow.cells[i].style.width = cellWidth + "px";
                }
            }

                // set the width of itemsDiv
            var itemsDiv = document.getElementById ("itemsDiv");
            itemsDiv.style.width = itemsTable.offsetWidth + "px";

                // if the vertical scrollbar of itemsDiv is displayed, itemsDiv must be wider
            var scrollWidth = itemsTable.offsetWidth - itemsDiv.clientWidth;
            if (scrollWidth > 0) {
                itemsDiv.style.width = itemsTable.offsetWidth + scrollWidth + "px";
            }
        }

    </script>
</head> 
<body onload="ResizeHeaderTable ()"> 

    <table id="headerTable" cellpadding="0px" cellspacing="0px" border="0px"> 
        <tr>  
            <td>1</td> <td>2</td> <td>3</td> <td>4</td> 
        </tr> 
    </table>

    <div id="itemsDiv">
        <table id="itemsTable" cellpadding="0px" cellspacing="0px" border="0px">
            <tr>  
                <td>123456789101112</td> <td>2938547</td> <td>34534546</td> <td>42222221134</td> 
            </tr> 
            <tr>  
                <td>123</td> <td>29385</td> <td>34534546444446232</td> <td>42222221</td> 
            </tr> 
            <tr>  
                <td>123456789101112</td> <td>2938547</td> <td>34534546</td> <td>42222221134</td> 
            </tr> 
            <tr>  
                <td>123</td> <td>29385</td> <td>34534546444446232</td> <td>42222221</td> 
            </tr> 
            <tr>  
                <td>123456789101112</td> <td>2938547</td> <td>34534546</td> <td>42222221134</td> 
            </tr> 
            <tr>  
                <td>123</td> <td>29385</td> <td>34534546444446232</td> <td>42222221</td> 
            </tr> 
            <tr>  
                <td>123456789101112</td> <td>2938547</td> <td>34534546</td> <td>42222221134</td> 
            </tr> 
            <tr>  
                <td>123</td> <td>29385</td> <td>34534546444446232</td> <td>42222221</td> 
            </tr> 
            <tr>  
                <td>123456789101112</td> <td>2938547</td> <td>34534546</td> <td>42222221134</td> 
            </tr> 
            <tr>  
                <td>123</td> <td>29385</td> <td>34534546444446232</td> <td>42222221</td> 
            </tr> 
            <tr>  
                <td>123456789101112</td> <td>2938547</td> <td>34534546</td> <td>42222221134</td> 
            </tr> 
            <tr>  
                <td>123</td> <td>29385</td> <td>34534546444446232</td> <td>42222221</td> 
            </tr> 
            <tr>  
                <td>123456789101112</td> <td>2938547</td> <td>34534546</td> <td>42222221134</td> 
            </tr> 
            <tr>  
                <td>123</td> <td>29385</td> <td>34534546444446232</td> <td>42222221</td> 
            </tr> 
            <tr>  
                <td>123456789101112</td> <td>2938547</td> <td>34534546</td> <td>42222221134</td> 
            </tr> 
            <tr>  
                <td>123</td> <td>29385</td> <td>34534546444446232</td> <td>42222221</td> 
            </tr> 
            <tr>  
                <td>123456789101112</td> <td>2938547</td> <td>34534546</td> <td>42222221134</td> 
            </tr> 
            <tr>  
                <td>123</td> <td>29385</td> <td>34534546444446232</td> <td>42222221</td> 
            </tr> 
            <tr>  
                <td>123456789101112</td> <td>2938547</td> <td>34534546</td> <td>42222221134</td> 
            </tr> 
            <tr>  
                <td>123</td> <td>29385</td> <td>34534546444446232</td> <td>42222221</td> 
            </tr> 
            <tr>  
                <td>123456789101112</td> <td>2938547</td> <td>34534546</td> <td>42222221134</td> 
            </tr> 
            <tr>  
                <td>123</td> <td>29385</td> <td>34534546444446232</td> <td>42222221</td> 
            </tr> 
            <tr>  
                <td>123456789101112</td> <td>2938547</td> <td>34534546</td> <td>42222221134</td> 
            </tr> 
            <tr>  
                <td>123</td> <td>29385</td> <td>34534546444446232</td> <td>42222221</td> 
            </tr> 
            <tr>  
                <td>123456789101112</td> <td>2938547</td> <td>34534546</td> <td>42222221134</td> 
            </tr> 
            <tr>  
                <td>123</td> <td>29385</td> <td>34534546444446232</td> <td>42222221</td> 
            </tr> 
            <tr>  
                <td>123456789101112</td> <td>2938547</td> <td>34534546</td> <td>42222221134</td> 
            </tr> 
            <tr>  
                <td>123</td> <td>29385</td> <td>34534546444446232</td> <td>42222221</td> 
            </tr> 
        </table> 
    </div> 
</body>

When the page has been loaded, the ResizeHeaderTable method is called. The ResizeHandlerTable method uses the offsetWidth property to retrieve and the style.width property to set the width of cells. Finally, it set the width of the div that contains the table for the items.

If you need further details about the offsetWidth property, the following link will be useful:

offsetWidth property

gumape
Nice solution, but the problem is that the computed width is not the same as the offsetWidth. At least it is not the same in my case.
Atticus