1

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?

Atticus
  • 1,622
  • 7
  • 32
  • 55
  • the 98% in the first table is needed because the scroll has a length of 2% and I want it not to appear as a part of the listing. – Atticus Aug 12 '10 at 09:41
  • You can edit your own question and put those side notes in it. Don't use comments for this. – Marcel Korpel Aug 12 '10 at 09:46
  • @Marcel Korpel: OK. I knew that I can edit I just did not want to make the question even longer. – Atticus Aug 12 '10 at 09:50

3 Answers3

2

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.

Community
  • 1
  • 1
Pekka
  • 442,112
  • 142
  • 972
  • 1,088
0

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">
<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 González
  • 142,137
  • 41
  • 261
  • 360
  • @Á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 Aug 12 '10 at 10:16
  • @Á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 Aug 12 '10 at 10:23
  • @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 Aug 12 '10 at 10:45
  • @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 Aug 12 '10 at 11:04
  • @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 Aug 12 '10 at 11:14
  • @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 `` elements the way we need. It's a pitty that the simple trick did not work but that's life :) – Álvaro González Aug 12 '10 at 11:49
  • @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 Aug 12 '10 at 17:00
0

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
  • 2,832
  • 2
  • 18
  • 9
  • 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 Aug 12 '10 at 12:12