I have a page layout that is based on tables, and as much as I would like to restructure it with more modern markup, that is not an option. The layout uses a cell that spans two rows as a sidebar on the right side, while the upper left cell contains a simple header, and the lower left cell contains the main content of the page. The top left cell has a fixed height, and the height of the bottom cell and right cell is not specified. I have created a simplified example that illustrates my problem:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<style type="text/css">
.fixed { height: 100px; }
table { border: 1px solid #000; }
td { border: 1px solid #ddd; vertical-align: top; }
tr { border: 1px solid #cfc; }
* { padding: 15px; }
</style>
</head>
<body>
<table>
<tr class="fixed">
<td>left</td><td rowspan="2"><div style="height: 500px;">right</div></td>
</tr>
<tr class="stretch">
<td>left</td>
</tr>
<tr class="footer">
<td colspan="2">footer</td>
</tr>
</table>
</body>
</html>
I have set the height of the right column inline at 500px to simulate content that is taller than the height of the two left columns. This behaves as expected in modern browsers: The height of the top left cell remains fixed, and the lower cell stretches to fill the extra space. But in IE8, both left cells are stretched vertically. I need the top cell to keep its fixed height. How do I get IE8 to honor the height specified for the top left cell using only CSS?
Edit:
Instead of setting the height on the right column td, I am setting the height on a div inside the right column.
I think Jeroen is right that there are no pure CSS solutions to this problem. Any time there are cells in a table with rowspan
set, IE is going to ignore any explicit heights set on those rows. The solution is to never use rowspan
. In my situation I was able to circumvent the problem by placing the content that was spanning two rows in the second row, leaving the cell in the first row empty, and using a negative margin to move the start of the content up into the first row. I hope this is helpful to somebody else. If anybody does have a pure CSS solution I'll accept that as the answer.
Interesting problem. Afraid the answer may be that there are no real solutions to the problem you describe, only workarounds. I found that adding some style to the second "left" td made the problem disappear, at least in your sample:
<td style="min-height: 500px;">left</td>
Hope that helps.
PS. IE9 had the same problem.
Even if a cell only contains an image, you must know that table cells have their height computed according to the position of the text baseline; and the current style of text has an impact on computing this baseline position and the line-spacing after it.
You may think that setting "line-height:1" would be enough to avoid this line-spacing, i.e. the margin gap that always occurs below every line of text. This is not enough. The simplest solution is to set "line-height:0.8" (or lower) for the cell containing the image, so that the 0.2em default added gap below the baseline (which is still infered as default due to the absence of text) will make the baseline fit in the cell height. Then you can properly place an image (or any fixed height element) in the cell whose height will determine the cell height, without having the cell height stretched.
Note: with this line-height, any text you would place in that cell would have its baseline just at the bottom of the cell, so that descenders will overlap the bottom padding, border, border-spacing of the current cell, or in the border, padding or content of the cell in the next row, or contents below the table if the cell was on the last row.
Tested on Google Chrome (current version 15)
Example (HTML5):
<!DOCTYPE html>
<html><head>
<title>Examples of image transforms (rotations and mirroring)</title>
<style>
table,tbody,tr,td,image{margin:0;border:1px solid #999;border-collapse:collapse;border-spacing:0;background:#FFF;color:#000;padding:0;vertical-align:middle;text-align:center;}
td.z{line-height:0;}
</style>
</head><body>
<table border="0" cellspacing="0" cellpadding="0">
<tbody><tr>
<td style="border-bottom:hidden">Normal 0° (1,0,0,1,0,0)</td>
<td style="border-bottom:hidden">Mirrored 0° (-1,0,0,1,0,0)</td>
<td style="border-bottom:hidden">Mirrored 90° (0,1,1,0,0,0)</td>
<td style="border-bottom:hidden">Normal −90° (0,1,-1,0,0,0)</td>
</tr><tr>
<td class="z"><image alt="" src="Avatar-220px.jpg" style="-webkit-transform:matrix(1,0,0,1,0,0);"/></td>
<td class="z"><image alt="" src="Avatar-220px.jpg" style="-webkit-transform:matrix(-1,0,0,1,0,0);"/></td>
<td class="z"><image alt="" src="Avatar-220px.jpg" style="-webkit-transform:matrix(0,1,1,0,0,0);"/></td>
<td class="z"><image alt="" src="Avatar-220px.jpg" style="-webkit-transform:matrix(0,1,-1,0,0,0);"/></td>
</tr><tr>
<td class="z"><image alt="" src="Avatar-220px.jpg" style="-webkit-transform:matrix(1,0,0,-1,0,0);"/></td>
<td class="z"><image alt="" src="Avatar-220px.jpg" style="-webkit-transform:matrix(-1,0,0,-1,0,0);"/></td>
<td class="z"><image alt="" src="Avatar-220px.jpg" style="-webkit-transform:matrix(0,-1,1,0,0,0);"/></td>
<td class="z"><image alt="" src="Avatar-220px.jpg" style="-webkit-transform:matrix(0,-1,-1,0,0,0);"/></td>
</tr><tr>
<td style="border-top:hidden">Mirrored 180° (1,0,0,-1,0,0)</td>
<td style="border-top:hidden">Normal 180° (-1,0,0,-1,0,0)</td>
<td style="border-top:hidden">Normal 90° (0,-1,1,0,0,0)</td>
<td style="border-top:hidden">Mirrored −90° (0,-1,-1,0,0,0)</td>
</tr></tbody>
</table>
</body></html>
Note the trick on class "z" for table cells (line-height:0) containing only an image, in order to make them fit exactly the image size.
The images shown in this example is a small square photo in 8 different orientations. There's only a thin 1px gray border enclosing each photo and its label displayed above or below, the photos are fitting exactly within the cell borders.
Note that the reorientation uses WebKit styles (for Safari and Chrome); you can add the equivalent properties for IE and Firefox by changing the prefix; for CSS3, no prefix will be needed. If not these transforms are not supported, the images will not be reoriented/mirrored, but they will still fit exactly the cell, without extra internal gaps.