Upcoming changes to absolute positioning in tables and table margin collapsing in Firefox 10
Last week I landed a number of patches which I’ve been working on which fix two very old (5 digit) bugs in Gecko (bug 10209 and bug 87277) which affect rendering of web content. This point summarizes the changes to the behavior of Firefox as a result of those patches.
The first behavior change is about absolute positioning of elements inside positioned tables. When you specify the CSS position: absolute style on an element in a web page, it is taken out of the flow of the web page, and its position is calculated relative to the nearest positioned ancestor in the DOM (by positioned, we mean an element which has a non-static position, i.e., one of fixed, relative or absolute for its position computed style. See this test case for a simple example.
For a long time, Gecko used to only look for inline or block positioned elements in the parent chain. So, for example, if you had a positioned table element inside a positioned block element, any position: absolute element inside the table used to be positioned relative to the outer block element, as opposed to the table element (which is the nearest positioned ancestor). This test case shows the bug if you load it in Firefox 7. In the correct rendering, the div with the red border should be placed ten pixels below the element with the green border, but in Firefox 7, it is positioned 10 pixels below the element with the red border.
The other behavior change is a fix to margin collapsing on table elements. Firefox used to have a bug which caused margins on table elements to not be collapsed with other adjacent elements. Take a look at this test case for example. Here we have an outer table with a height of 180 pixels, in which there are 4 div elements, each with the height of 20 pixels, and with 20 pixels margins on each side. The correct rendering for this test case is for the 4 inner divs to be laid out evenly spaced in the vertical direction in the outer div. This happens because the bottom margin of the first inner div is collapsed with the top margin of the second div, which makes the content of the second inner div to be laid out 20 pixels below the content of the first inner div.
Now, if you make the inner divs tables instead (as in this test case), you can see the bug in Firefox 7. What’s happening is that the vertical margins between tables are not collapsed, which effectively means that the contents of the each of the tables will be 40 pixels below the previous one, making the 4 tables overflow the height of their container. If you try this test case in Firefox trunk, you will see that the rendering is identical to the rendering of the test case using inner divs instead of inner tables.
Note that this fix is not specific to the case of adjacent tables. This test case interleaves divs and tables. The rendering should be identical to the previous two test cases in Firefox trunk now.
It should be obvious that since these two changes affect the rendering of web pages, they may break existing web sites. Indeed, today we had our first bug report about this behavior change. The good news is that these two changes make us more compliant to the CSS specification, and all other web browser engines implement these cases correctly, so web sites which are affected by these two changes have been relying on a bug in Gecko, and have probably been already broken in other web browsers for a long time. These fixes bring Gecko on par with other browser engines.
You can test this fix in Firefox Nightly right now. If you see this change affecting a website you own, please let me know if you need help in fixing it. If you see this change affecting websites you do not own, please let me know and I’ll try to contact the website and help them fix the problem. If you see a behavior change which you think is not intentional and is a regression from these changes, please file a bug and CC me on it.