Absolutely-positioned table header (th) - which browser is wrong? - html

This simple table with one absolutely-positioned column renders differently in Firefox (and IE) than in Chrome (and other Webkit-based browsers):
http://jsfiddle.net/WZ6x8/
<div>
<table>
<tr>
<th class="absolute"> </th>
<th> </th>
</tr>
</table>
</div>
* {
margin: 0;
padding: 0;
}
table {
border-collapse: collapse;
table-layout:fixed;
}
th {
border: 1px solid black;
width: 100px;
}
.absolute {
left: 0;
position: absolute;
}
div {
margin-left: 100px;
}
Why is there a difference? Which browser is wrong (according to the standard)? How can this be fixed to work on all browsers, without removing the line border-collapse: collapse?
Edit: as noted by #urzeit, "If you specify top: 0; the output in firefox is the same as in chrome." However, there are two issues: first, with multiple rows, top: 0; collapses them all into one; second, the right edge of the absolutely-positioned column extends one pixel too far. You can see both issues at http://jsfiddle.net/WZ6x8/3.

This is caused by rounding issues which are often inconsistent across browsers, and are probably the same ones that plague things like background offsets, percentage calculations and so on.
In a nutshell, the reason why rounding issues come into play is found in section 17.6.2 which, as you may have guessed, describes the collapsing border model:
Borders are centered on the grid lines between the cells. User agents must find a consistent rule for rounding off in the case of an odd number of discrete units (screen pixels, printer dots).
And:
The top border width of the table is computed by examining all cells who collapse their top borders with the top border of the table. The top border width of the table is equal to half of the maximum collapsed top border. The bottom border width is computed by examining all cells whose bottom borders collapse with the bottom of the table. The bottom border width is equal to half of the maximum collapsed bottom border.
Since the border width is 1 pixel, which is an odd number, rounding issues occur when attempting to halve that value. So the question of which browser is wrong — or if any of them are — is debatable.
Unfortunately, because this is a rounding issue, it's not possible to work around this using pure CSS unless through inconceivably elaborate hackery, and very difficult to do so using a script as browsers tend to be inconsistent when reporting decimal/fractional offset values as well (in particular, Firefox, IE and Chrome all report wildly different values for offsetTop of your table-cell and its next sibling).
While I can't offer a solution to your problem, hopefully at least I've helped you understand why browsers are behaving the way they do.
Here's the nitty gritty if you're interested in why the issue ultimately lies in the way the collapsing border model is defined.
Section 9.7 states that if an element is absolutely positioned, then its display is set to block, even if it would otherwise be a table-cell. In all browsers, the computed display for that th is in fact block, so no problem there.
As you've correctly pointed out, the containing block of your table cell is the initial containing block. This removes it from its usual containing block which would otherwise be the table. Section 10.6.4 does add that that if your cell does not have any specified height, top or bottom offsets, i.e. they are all auto, then it should remain in its static vertical position and measurements made accordingly. (Likewise the horizontal position is accounted for in section 10.3.7, however since you've given it left: 0 and width: 100px, it gets shifted to the left edge and its width is as specified, excluding the borders.)
But what is this static vertical position? Because it would ordinarily be display: table-cell if it wasn't absolutely-positioned, the static position, and its corresponding measurements, is determined by its position in the table.
Your given table layout is covered by the following subsections of section 17:
17.5 Visual layout of table contents
17.5.2.1 Fixed table layout
17.6.2 The collapsing border model
Section 17 contains elaborate descriptions on how tables, captions, table-rows and table-cells should be laid out. A lot of it is based on HTML, and certain sections are left vague and/or undefined for various reasons. Fixed table layout is pretty well-defined though, and in this case it is not even relevant.
Section 17.5 says this near the bottom:
The edges of the rows, columns, row groups and column groups in the collapsing borders model coincide with the hypothetical grid lines on which the borders of the cells are centered. (And thus, in this model, the rows together exactly cover the table, leaving no gaps; ditto for the columns.)
And:
Note. Positioning and floating of table cells can cause them not to be table cells anymore, according to the rules in section 9.7. When floating is used, the rules on anonymous table objects may cause an anonymous cell object to be created as well.
Which, of course, has been explained just above.
But if an absolutely-positioned table cell is no longer a cell, what happens?
A "missing cell" is a cell in the row/column grid that is not occupied by an element or pseudo-element. Missing cells are rendered as if an anonymous table-cell box occupied their position in the grid.
So while the actual th box is absolutely positioned, it leaves an anonymous "ghost" cell in its place in order for the table to be rendered properly. This anonymous table-cell is empty and does not inherit the styles from the actual table-cell, so it has no intrinsic width.
However, because the actual table-cell's vertical position is static, it is still affected by how the table is rendered, which brings us to section 17.6.2 on the collapsing border model.

multiple rows - Try this css..
<style>
.absolute {
left: 0;
margin-top: -1px;
border-right:0px;
position: absolute;
}
#media screen and (-webkit-min-device-pixel-ratio:0)
{
.absolute {
margin-top: 0px;
}
}
</style>
Chrome And Firefox Demo Screenshot.

The reason this is happening is because you've specified the entry as absolute, meaning firefox's browser style where it sets the "top" css property to 1px is being used. If you want to avoid this you might be able to use a css reset file which blows away browser-specific default formatting.
As for your issue with setting top:0 resulting in the cells collapsing into each other, that is the correct behavior. Absolute renders in the space of the closest positioned CSS element. Think of it as if the element is no longer in its usual place in the DOM. If the two cells specified as absolute have the same closest positioned parent element (in this case the body) then they would both render relative to the same place with each having the top:0 property which means they would overlap.
I don't think either is wrong, you're just running into the (common) issue of browser styles.

In short ,
There are two problem to me in this problem
a) The first problem is overlapping of left <th> with right <th>
The correct browser is one which overlapp the <th> because
you are firstly giving the outer div margin-right:100px;
the <th> with aboslute property should fit this area, but the extra border of 1px increase the width by 2px(left border + right border) .Hence the overlap is correct
b) The second problem is of top margin for the left element
It can be removed by adding
th{
top:0px;
}
This is because of browser effect to html page

Related

Is the collapsing border model's implementation in web browsers valid?

I have been trying to understand this excerpt from CSS 2.2 specification for a while with no success (the bold selection is mine):
UAs must compute an initial left and right border width for the table by
examining the first and last cells in the first row of the table. The left border width of the table is half of the first cell's collapsed left border, and the
right border width of the table is half of the last cell's collapsed right
border. If subsequent rows have larger collapsed left and right borders,
then any excess spills into the margin area of the table.
The top border width of the table is computed by examining all cells who
collapse their top borders with the top border of the table. The top border
width of the table is equal to half of the maximum collapsed top border.
And this is how borders, collapsing etc. are implemented in Chrome (FF and IE > 7 are the same):
table {
border: 6px solid green;
border-spacing: 0;
border-collapse: collapse;
}
#cell_1_1 {
border: 28px solid red;
}
#cell_2_1 {
border: 12px solid chartreuse;
}
#cell_2_2 {
border: 2px solid cyan;
}
While I was expecting something like this:
I was expecting the left border of the table to be 14 px thick. Because the collapsed left border of the first cell #cell_1_1 is 28px wide (The left border width of the table is half of the first cell's collapsed left border) and on the left the border is split between the cell and the table. So visually the table has 28 px border near the first cell, but 14 px belong to the border of the first cell. And then the border stays the same for all the left side of the table. If some cell's borders a wider then they are protruding to the left, without affecting the left border of the table.
The same thing with the top border.
Also I thought the problem can be related to the initial word in the excerpt, that is these rules apply only in case a table has no specified border, but it turned out to be not related (the removal of the border style rule for the table simply removed the green border at all).
So could anyone answer to the next questions:
whether the implementations of this collapsing borders model in Chrome, FF, IE are correct?
if they are correct, what is wrong with my understanding of the specification?
Now, if we went vice versa and assumed the implementation in Chrome as a starting point to derive the specification, this part should have been something like the next (I have kept only the part relevant to the left border for succinctness):
UAs must compute an initial left and right border width for the table which is then used to position the table relatively to its containing block by
examining the first and last cells in the first row of the table. The left border width of the table is half of the first cell's collapsed left border after all border conflicts if any have been resolved
...
If subsequent rows have larger collapsed left and right borders,
then any excess spills into the margin area of the table.
...
Any borders that spill into the margin are taken into account when
determining if the table overflows some ancestor (see 'overflow'), but do not affect the position of the table relatively to its containing block
Then the excerpt would have made sense.
Here there is a table with the border wider than the first cell's one inside a containing block with the pink background (as we can see, the border of the table is chosen over the border of the first cell because it is wider and then this border is used to position the table inside the container. The wider borders of the subsequent cells are protruding beyond the table's border):
And here there is the same table with the border of the first cell wider than the table's one, that is chosen over it during the border conflict resolution. And here this border is used to position the table relatively to the container:
The answer is "no." I love the frankness of the discussions had by the CSSWG, and the notes on the current draft of the CSS Tables 3 editors' draft tell you all you need to know about this question.
Since browsers
handle this so differently, convergence cannot happen without
reimplementation. …
… some combinations are not well-posed problems, so no
rendering algorithm could be optimal.
Because they grew from something simple (HTML) to something very
complex (HTML+CSS), the current table rendering models…used by web browsers are insane (in the sense they are
buggy, not interoperable and not CSSish at all). Many usual CSS
assumptions are broken, and renderings diverge widely.
(Emphasis added.)
There's much more information in the current draft, but the CSS Working Group acknowledges (1) that browser implementations are inconsistent, and (2) even their own current proposal is insufficient.

Unexpected padding in <td> despite nothing in CSS making it this way

I'm trying to make a basic A4 document in HTML using mm CSS sizing. The document is sized perfectly - it prints fine on A4, covering virtually the full page, leaving a nice 3mm margin around it. I'm using a table for the layout, as the original document (that i'm re-creating in HTML) was created in Excel, and therefore has a table structure.
As I need the table to have an exact 3mm margin, i'm setting the width and height in mm, and using absolute positioning (3mm top and left). I had originally created the table-like layout using divs - but making the lines overlap perfectly using this is extremely fiddly - you can't really do it properly, as you're working with a mixture of millimetres and pixels, hence my choice for using a table.
The table displays perfectly, all rows uniformly fill the document. Some of the rows need to be split, so I chose to use floated divs within the s, within the s.
Despite resetting the CSS, and setting the <tr>s padding to 0, and the <td>s padding to 0, and giving the table border-collapse: collapse; and border-spacing: 0;, there's an annoying little margin between the div, that even Chrome can't explain why it's there:
https://www.dropbox.com/s/qt1n54m9fxxl6f2/job_sheet_template.html
You may need to open the image link, and zoom in, to see the green highlighted space below the divs (which is apparently the <td>s padding). In the bottom, right hand corner, you can see that the padding isnt set?
Why is this here?
Your image shows that border collapse isn't being applied. Try using:
table {
border-collapse: collapse !important;
}
I've fixed the problem -
The padding isn't set, but somehow setting the divs height to 100% doesn't work - I've now set it to 5.4mm which fits perfectly.
for html
html
{
font-size:0;
}

What can cause table columns to end up narrower than their definition?

I've got a CSS rule:
#map td {
border: medium none;
height: 32px;
margin: 0;
padding: 0;
width: 32px;
}
And I have a table inside an element called map. Each cell of the table is supposed to contain an image that's 32x32 pixels in size. But when I render it, either in Firefox or in Chrome, the map grid ends up severely squished under certain circumstances.
Examining it in Firebug, I find that the styles are all applied correctly, with the #map td style as the dominant rule for the cells in question, but when I look at the Computed tab, it gives the width property (under "Box Model") as 14.6167px. If I expand the width node, the only thing under it is: #map td 32 px, so I'm a bit at a loss as to what's causing all of my columns to be so much narrower than 32 px.
I'm sorry that this isn't much to go by, but I'm still fairly new to CSS so I don't know a lot of the right questions to ask. Does anyone know what can cause something like this to happen, and how I can deal with it?
UPDATE: After a bit of experimenting, trying to narrow it down to a simple, reproducible test case, it seems to be that the sidebar div is "squeezing" the main div and there's not enough room, so the browser is making the main one narrower, because when I remove the sidebar, everything goes back to the correct width. So now the question is, how do I set this up so that the width of the table is enforced as described and can't be squeezed by other elements to the side of it?
Keep your td/th with a defined width like you've already done.
For your table, set the layout to fixed, and you'll also have to define a fixed width as well.
table{
table-layout: fixed;
width: 64px;
}

TD height = total height of contained divs?

I can't believe I can't find this question here or on Google - it seems such a dumb one I'm embarrassed to ask, but here goes as it's driving me nuts this morning...
Imagine a single-column, stacked bar chart made with divs like this to look a bit like a thermometer:
<div id="thermo">
<div id="thermored"></div>
<div id="thermogreen"></div>
</div>
#thermo is the containing div, #thermored is the full height background and #thermogreen is the overlay that will be changed to reflect data - in the real world it shows percent complete of a task.
As this stands, it works. However, it needs to work inside a table cell (not my choice - it's a system restriction on the CMS). The problem is that the height of the containing TD is (despite trying fixed heights) the total of the two divs, even though they are positioned relatively and overlayed.
Here's the current css - it's not pretty as I've been trying so many combinations of positioning over the last couple of hours
#thermo{
width:140px;
height:500px;
position:relative;
}
#thermored{
width:50px;
height:100%;
margin-left: 20px;
background-color: red;
}
#thermogreen{
width:50px;
height:280px;
margin-left: 20px;
background-color: green;
position:relative;
bottom: 280px;
float:left;
}
*EDIT For info the issue I'm having is in Chrome and FF - IE(8) sets the TD height they way I want
I think the problem you're having comes from the fact that relative positioning leaves elements in normal flow. Have you tried setting position: absolute; for the inner thermogreen div? Absolute positioning takes elements out of normal flow, and therefore the td tag will only take into consideration the height of your thermo div, which is set to 500px in height. (Edit: you can actually leave thermored with no position attribute. It's set to 100% of the height of the thermo div, meaning no matter what your td will be 500px in height, and you have less CSS to worry about).
Have a look at the jsfiddle I came up with:
http://jsfiddle.net/dgRCu/3/
Does this solve your issue? It seems the td has stayed at 500 pixel height instead of expanding to 700+ now.
I'm not sure what the intended purpose of these divs are so I set bottom: 0; on the thermogreen div since it seems what you want is for the green bar to expand in height while the red bar is the background color.
TD cells will collapse/expand to the size of the 'tallest' height. Using css within the cells are going to cause different issues with different browsers or especially email readers.
So, you have tried:
<tr>
<td height="500"></td>
</tr>
And then, putting those block elements in there? Make the height on the first td cell of your table and make it more than the total of the two divs.
You're floating one so the largest should be forcing the height.
Have you used the Dev Tools in IE to see how the table cells are being rendered? Any chance you can make a jsfiddle.net of just the html table and css code?

Weird margin differences between Chrome/Safari and Firefox

I recently designed a website (http://willryan.us/typefun01), mainly using Chrome while coding to test. I recently noticed that there are some weird things happening at the end of certain sections, (the gap after History, the overlap of Styles onto Anatomy).
I have a css reset in my stylesheet (not sure if that has anything to do with this), and I can't figure out what's causing this, and how to get the site to look like how it does when viewed in Chrome
The gap after History is due to:
#historyWide {
margin: 250px 80px 75px;
}
It could be remedied with:
div#content > div {
overflow: hidden; /* or auto */
}
You could also move the large top and bottom margins of elements inside the child divs of #content to padding on the child divs themselves. Anything will work as long as it's all contained by those child divs.
You're simply seeing the different ways that browsers handle imperfect layout.
If you want to avoid the gap after History you would want to use a padding in historyWide instead of a margin; the margin pulls aways elements while padding makes them bigger
On anatomy what's happening is that you're using the property "top" to modify #styles, this will move the element but the parent will reserve only the original space for the element. You will be better off working with margins and padding than with "top" if you have to keep a relation between the elements.
Lastly, i woulnt position elements with margins like you did with #stylesMono. I think you could better work with paragraphs to keep keep the vertical position and, from there, working with floats, margin and padding in the scope of the "p".