- From: Anton Prowse <prowse@moonhenge.net>
- Date: Sat, 28 Aug 2010 11:37:51 +0200
- To: www-style list <www-style@w3.org>
- CC: Bruno Fassino <fassino@gmail.com>, fantasai <fantasai.lists@inkedblade.net>
On 26/08/2010 01:18, Anton Prowse wrote: > We can solve this with the following modification of 9.5.2, which > bypasses 8.3.1.6.2 once clearance is introduced, for the situation that > causes us difficulty: > > # If this hypothetical position of the element's top border edge is > # not past the relevant floats, then clearance <del>must be</del> > # <ins>is introduced and margins collapsed anew according to the rules > # in 8.3.1. However, if the element's top and bottom margins > # collapse, and the resulting margin collapsed with the parent's top > # margin when the hypothetical position was calculated, then the > # element's top border position is taken to be the same as that of a > # hypothetical immediately-following sibling with zero top margin and > # non-zero top border rather than that specified in 8.3.1. > # > # Then the amount of clearance is</ins> set to the greater of: > > This introduces a change only in the narrow case we're interested in. > What we're doing is engineering the situation to ensure that the > element's bottom margin doesn't influence the size of the collapsed > margin below the redefined top border edge position. > It doesn't affect the clearing element's subsequent siblings, in the > sense that these remain in positions at least as low as the clearing > element's position (due to 8.3.1.6.2's bottom border device). If desired, we could go one step further and remove the discontinuities that the clearance concept has historically introduced. Specifically, when a self-collapsing clearing element collapses with its parent and with self-collapsing following siblings, the position of the following siblings (currently at the same position as the parent due to 8.3.1.6.1) may change, relative to the clearing element, if clearance is introduced, due to the use of 8.3.1.6.2 (no collapsing with parent) to calculate their new position. The following test case demonstrates this phenomenon: <div>before</div> <div style="float:left; width:50px; height:50px"></div> <div> <div style="clear:left"></div> <div style="margin-top:20px"></div> <div>next</div> </div> Under every clearance proposal touched upon so far (including the current spec, the pre-2007 spec, and my own proposal above), the second child's position is the same as the first child's prior to clearance, but moves to 20px below the first child's once clearance is introduced. To address this, move my above modification to 8.3.1 (which is arguably where it should have been anyway) and tweak that section with a new 8.3.1.6.2.2 as follows: # If the top and bottom margins of a box are adjoining, then it is # possible for margins to collapse through it. In this case, the # position of the element depends on its relationship with the other # elements whose margins are being collapsed. # * If the element's margins are collapsed with its parent's top # margin, the top border edge of the box is defined to be the # same as the parent's. # * Otherwise, either the element's parent is not taking part in # the margin collapsing, or only the parent's bottom margin is # involved. |<ins> * If the element has clearance but its margins collapsed with | its parent's top margin when _determining if clearance were | needed_<link to appropriate paragraph of 9.5.2>, the top | border edge position is the same as that of a hypothetical | immediately-following sibling with zero top margin and | non-zero top border. | * Otherwise, if the element's margins are collapsed with the | top margin of a previous sibling that has clearance and | whose margins collapsed with its parent's top margin when | _determining if clearance were needed_, the top border edge | position is the same as that previous sibling's. # * Otherwise,</ins> the position of the element's top border # edge is the same as it would have been if the element had a # non-zero bottom border. The new bullet point ensures that subsequent self-collapsing siblings still line up alongside the clearing element, as they did before clearance were introduced. > [..] (Note that this is unlike the situation arising from some unnatural > notion of hypothetical top border edge being used in 9.5.2, in which a > child's hypothetical position could end up higher than its parent's > actual position, causing pathological cases when both parent and child > have clear set. In fact, the case of parent and child both with clear set presents difficulties anyway, whatever the clearance implementation details we decide upon. Consider the following test case (or just jump to the conclusion eight paragraphs further down!): <div>before</div> <div style="margin-top:20px"> <div style="float:left; width:40px; height:40px">A</div> <div style="margin-top:40px; clear:left"> <div style="float:left; width:30px; height:30px">B</div> <div style="margin-top:50px;clear:left">grandchild</div> </div> </div> For ease of description, let's set up a y co-ordinate axis with 0 flush with the bottom of "before" and y>0 heading downwards. First assume that we handle the child clearing element before the grandchild clearing element. Assuming clear:none on all elements, there's a 50px collapsed margin below which lies the top border edge of all three in-flow divs at y=50. Clearance is introduced for the child, the top of float A moves upwards to y=20 and the child (and hence the top of float B) moves downwards to y=60, flush with the bottom of float A. Clearance is introduced for the grandchild – and we have to stop and decide what's supposed to happen to the child. Presumably the child doesn't now change position, even though its top margin no longer collapses with that of the grandchild and even though the grandchild's margin was the only reason the child has ended up as low as it currently is? (I'm pretty sure I can come up with some fairly evil scenarios if recalculation is permitted.) So, assuming the child stays where it is, the grandchild ends up at y=90, flush with the bottom of float B. Now assume that we handle the grandchild clearing element before the grandchild clearing element. Assuming clear:none on all elements, clearance is introduced for the grandchild, the top of floats A and B move upwards to y=40, and the grandchild moves downwards to y=80, flush with the bottom of float A. Next, clearance is introduced for the child – and we have to stop and decide what's supposed to happen to the grandchild. Again, let's suppose that the grandchild stays fixed. The top of float A moves upwards to y=20 and the child (and hence the top of float B) moves down to y=60. The position of the grandchild is 10px *above* the bottom of float B – which forces a recalculation for the grandchild to move it to flush with the bottom of float B. With this test case, the final renderings are the same. However, if we respecify the height of floats A and B as 20px and 10px respectively, the final renderings are different: the parent is at y=20 and the grandchild at y=60, yet the child is at y=50 when the child is handled before the grandchild but at y=40 when the child is handled after the grandchild. (This time, no recalculation is necessary in the latter case.) To conclude, the clearance concept remains underspecified. The least troublesome approach would be to state that clearing elements are treated in depth-first tree order, and that once calculated, an element does not change position when performing clearance calculations for subsequent elements. Cheers, Anton Prowse http://dev.moonhenge.net
Received on Saturday, 28 August 2010 09:40:01 UTC