In what might be the first major Firefox 3 CSS positioning bug, using clear:both can affect the layout of absolutely positioned elements elsewhere in the document when the page is resized, under certain circumstances
UPDATED 29/06/2008 - Bugzilla report filed
Description
This is a curious bug, for several reasons. I'll go through the logic for a case you might encounter it in a second. Firstly, I'll just spit it out and describe the bug in full.
If an element is set to clear:both and all it's prior siblings are floated, then any of the clearing element's parent's sibling elements that have position:absolute and more than one position declaration will not have their position and dimensions updated upon page resize.
Phew. Well, that's not too complicated, is it? Another way to look at it is this: if you"re using absolute positioning for part of your layout, and one of the main layout elements contains floats, and you decide to clear the floats with something, you might end up with page elements becoming "frozen" - when the page is resized, they will stubbornly refuse to move or update.
Scenario
Allow me to describe a possible layout that might bring this bug into consideration. Yep, this layout is pretty close to that of one of my projects. Which broke as soon as Firefox 3 came out. Making me cry. Hence my interest in the matter. The layout we want...
- Is elastic
- Has a minimum height/width
- Needs a sticky Footer
- Needs a content area that always totally fills any space not used by the header, footer and sidebar
This is the basic layout we want to use, illustrated in simple blocks. For those curious as to why we'd want this layout, imagine it for an app of some kind, not a site with primarily textual content; a map-, or video-, or flash-based gadget. For more info in the layout itself, and its techniques, see Rob Swan's Conflicting Absolutes article at ALA.
So, the sidebar is absolutely positioned (this example has top, right and bottom declarations, but only two are needed to trigger the bug) below the header. Go ahead, resize the page. All is good. So let"s add some content to the header.
The bug, demonstrated
We want to have an H1 floated over to the left, something floated over to the right, and a menu that falls below both of these. Not a terribly implausible layout for a header. So let's put it in, and see what happens.
The sidebar positions correctly when the page loads, but not when the browser window is resized. It becomes "frozen".It's worth noting that refreshing the page or changing a stylesheet attribute with firebug puts the element in its correct position, but it remains frozen. Which sounds like the old reflow bugs, although I'm no expert
Conditions
The exact criteria for triggering this bug are, perhaps, fairly rare, as they're pretty specific. These are my findings so far of various permutations and alterations.
- The clearing element has to clear all it's prior siblings: removing either one of the floated elements, or simply removing their float declaration, or indeed having a non-floated element anywhere before the clearing element, prevents the bug from triggering.
- Subsequent siblings of the clearing element do not affect the issue.
- The absolutely-positioned element needs more that one position declaration (two or more of left, top, right and bottom) for the bug to trigger.
- The first shared ancestor of the relevant elements - that is, the parent of the absolutely-positioned element, and the grandparent of the clearing element - must have position:relative to trigger the bug. This is quite likely, since the absolutely-positioned element (in this case the sidebar) is calculated from its nearest positioned ancestor, which you"ll often want to be its parent. For example, in the demo, removing position:relative from the pageWrapper element will prevent the bug. sidebar will then calculate its position from the Body element - in this case, that's manageable, but that depends on your layout.
- This bug affects any absolutely-positioned siblings. If, on the demo page, footer is given left:50%, for example, it will also become frozen.
- This includes elements that are before the clearing elements' parent in the hierarcy. For example, adding an absolutely-positioned "pre-header" div with left:50%;top:0 will also become frozen.
This, at least, is as far as I've got with investigating the bug. If I weren't so lazy, I'd do a full set of simpler test cases with various siblings, ancestors, etc and do some serious firebuggin'. I'll get round to it if a bugzilla report becomes necessary (see below).
Hopefully there's enough info here for anyone proficient in the mystical, magical code behind gecko to find the bug.
Workarounds
Well, just take your pick of some of the criteria above. A wrapper element here or there, or a non-floated element in amongst the problematic float/clear section, are probably the most straightforward.
Some comments
What makes this bug so very, very odd is that using clear:both ends up affecting elements that are not in the same place in the hierarchy as the clearing element: given their hierarchical positions, styling one should never affect the other, should it? The bug 'travels', as it were, up the hierarchy and across. This dazzlingly weird behaviour, in my opinion, puts the mysticism of IE's good old hasLayout troubles to shame.
There's no logical reason - at least, to my humble mind - why clearing a float should ever affect the absolutely positioned 'uncles'. It's not like someone, somewhere must have thought it was a good idea; it's simply broken, a good old-fashioned head-scratcher that some poor Mozilla dev is going to end up crying into his coffee over. Sorry. And just when they thought they'd killed the reflow bugs...
Reporting & Feedback
Some possibly related bugs: 271776 I'll confess now, I find bugzilla deeply intimidating and have hence not done too much digging to see if this bug has already been reported - a few cursory searches a few days ago didn't turn up anything conclusive. Even if it has been reported, hopefully this page will serve as a useful resource for anyone encountering the bug. If this is a known bug, please let me know. I will continue to hunt bugzilla for it, or something close, and will submit it when I reasonably believe I won't be duplicating a bug
Update 29/06/08 - This has now been submitted as bug #442542
I can confirm this behaviour on Windows XP, Mac OSX Leopard & Windows 2000.The full Firefox version string from About>Help is Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.9) Gecko/2008052906 Firefox/3.0. If you can confirm this bug in any other environments, or if anyone still has the old Release Candidates and can confirm its existence in one of those, it may serve as useful info.
If you have any other info on this or any similar bugs, please comment! If you're a member of any CSS-related mailing lists, forums or groups or any kind, please consider spreading this issue - I, for one, would like this bug fixed so I can stop weeping into my keyboard over an otherwise perfect layout ruined!Oh, and while you're at it, let me know what you think of my quick n' dirty attempt to freshen up the Blogger Minima template. Not bad for a start, I think.
Test Cases - Added 27/06/08
Here are the test cases I've prepared for Bugzilla report #442542
- Test page 1 - bug is triggered. Minimal version of above demo.
- Test page 2 - bug is not triggered. Positioning of the absolutely-positioned problem element changed.
- Test page 3 - bug is triggered. Presence of other siblings of the absolutely-positioned element does not affect bug.
- Test page 4 - bug is not triggered. Presence of prior, non-floated sibling of the floats prevents the bug.
- Test page 5 - bug is not triggered. A floated wrapper div prevents the bug.
- Test page 6 - bug is not triggered. An absolutely-positioned wrapper div prevents the bug.
- Test page 7 - bug is triggered. The bug affects mutliple absolutely-positioned elements, in any source order.
0 comments:
Post a Comment