Skip to content

[css2] 2 elements may get clearance, 1 suffices to avoid floats, how to pick? #9013

@Loirooriol

Description

@Loirooriol

I want to properly implement https://drafts.csswg.org/css2/#clearance on Servo but I'm not sure about this:

<!DOCTYPE html>
<div style="float: left; width: 25px; height: 25px; background: cyan"></div>
<div style="height: 50px"></div>
<div id="a" style="clear: both; width: 100px; outline: solid">
  <div id="b" style="clear: both; width: 50px; margin-top: -40px; outline: solid magenta; position: relative"></div>
</div>

First, to determine whether #a needs clearance, we find its hypothetical position by assuming clear: none. However, the result depends on whether #b gets clearance or not:

Option 1: Assuming #b gets clearance

    Then #b's margin doesn't collapse with #a, so we get something like: (position of #b still unknown)

    The hypothetical position of #a is past the relevant float, so no clearance is introduced.

    Then we find the hypothetical position of #b by assuming clear: none, so collapsing the margins:

    The hypothetical position of #b isn't past the relevant float, so we need to add clearance as we assumed, avoiding margin collapse:

    The clearance is the amount necessary to place the border edge of the block even with the bottom outer edge of float, that is, 15px. The spec also allows flooring this by the amount necessary to place the top border edge of the block at its hypothetical position, 0px, but this would still result in 15px. Adding this clearance, we finally get

Option 2: Assuming #b doesn't get clearance

    Then the margins collapse and #a is moved upwards, overlapping the float: (position of #b still unknown)

    The hypothetical position of #a isn't past the relevant float, so we need to add clearance.

    The clearance is the amount necessary to place the border edge of the block even with the bottom outer edge of float, that is, 15px. The spec also allows flooring this by the amount necessary to place the top border edge of the block at its hypothetical position, 0px, but this would still result in 15px. Adding this clearance, we get: (position of #b still unknown)

    Then we find the hypothetical position of #b by assuming clear: none:

    The hypothetical position of #b is past the relevant float, so no clearance is introduced, as we assumed.

Option 3: Not assuming anything

    Instead, tentatively compute #b's clearance (while still treating #a as clear: none), then use that information to compute if #a's clearance, and finally compute #b's actual clearance.

    So treating both #a and #b as clear: none:

    The hypothetical position of #b isn't past the relevant float, so we need to add clearance to #b. Therefore we proceed as in option 1.

Blink matches what I expect in options 1/3, Gecko and WebKit match what I expect in option 2.

Options 1/3
(Blink)
Option 2
(WebKit, Gecko)

I guess things would get interesting with options 1 and 2 if we assume that #b will get clearance but it ends up not needing it, or viceversa. Option 3 seems best, but more annoying/expensive to implement?

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions