Skip to content

[css2][css-flow][cssom] How does avoiding floats affect margins? #9174

@Loirooriol

Description

@Loirooriol

https://drafts.csswg.org/css2/#floats

The border box of a table, a block-level replaced element, or an element in the normal flow that establishes a new block formatting context (such as an element with overflow other than visible) must not overlap the margin box of any floats in the same block formatting context as the element itself. If necessary, implementations should clear the said element by placing it below any preceding floats, but may place it adjacent to such floats if there is sufficient space.

So the vertical adjustment to avoid floats is done with clearance, but what mechanism is used for the horizontal adjustment?

I see 2 reasonable options:

  1. The float is avoided by changing the used value of margins
  2. The float is avoided by adding some extra space additional to the margins. These space should then be taken into account in the equation in https://drafts.csswg.org/css2/#blockwidth

The thing is that getComputedStyle exposes the used margins: https://drafts.csswg.org/cssom/#resolved-value-special-case-property-like-height

If the property applies to the element or pseudo-element and the resolved value of the display property is not none or contents, then the resolved value is the used value. Otherwise the resolved value is the computed value.

However, note that for Gecko, Blink and WebKit, the used value is only for a computed auto. For a computed <length-percentage>, they just absolutize it into a length, even if there is over-constrainment and the used value is a different amount.
Servo still provides the used value even for a computed <length-percentage>.

Then, consider

<!DOCTYPE html>
<div style="border: solid; display: flow-root; width: 200px">
  <div style="float: left; width: 50px; height: 50px; background: cyan"></div>
  <div id="target" style="display: flow-root; height: 100px; background: magenta; margin-left: auto; margin-right: auto; width: 100px"></div>
</div>
<script>
document.body.append(getComputedStyle(target).marginLeft + ", " + getComputedStyle(target).marginRight);
</script>

Note that this is not clear in CSS2, but on all browsers the auto margins center the element within the space next to the float, not within the containing block:

This is what browsers say:

  • Gecko: 0px, 0px. auto is typically resolved to the used value, but just to 0px in the presence of floats.
  • Blink: 50px, 50px. Just resolves auto according to https://drafts.csswg.org/css2/#blockwidth, ignoring floats, without taking floats into account, even if the layout is completely different.
  • WebKit: 25px, 75px. It resolves margin-left: auto to the space between the rightmost left float to avoid and the border (like option 2 above). But then it resolves margin-left: auto according to https://drafts.csswg.org/css2/#blockwidth, ignoring floats.
  • Servo (option 1 above): 75px, 25px
  • Option 2 above: 25px, 25px

The behaviors of Gecko, Blink and WebKit seem nonsensical to me.

Also, if we want round-tripping, we must go with option 1 (or change how auto behaves in the presence of floats, but that seems more risky for compat).

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Status

    Monday afternoon

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions