Re: [css-box] shrink-to-fit and floats

On Mon, Mar 7, 2016 at 2:08 PM, Pavel Panchekha <me@pavpanchekha.com> wrote:
>> The section's size is well-described by the specs already.
>> In particular, section 10.3.5 defines how to calculate the shrink-to-fit
>> width of the section
>
> Yes, I understand that the shrink-to-fit of the section must be computed.
> However,
> I think this section does not fully explain the algorithm to use.
>
>> the "preferred width" and "preferred minimum width" are both 10px
>
> This is what I cannot justify. The standard (CSS3-box, §9.11, or CSS2.1,
> §10.3.5) say:
>
>> Roughly: calculate the preferred width by formatting the content without
>> breaking
>> lines other than where explicit line breaks occur, and also calculate the
>> preferred
>> minimum width, e.g., by trying all possible line breaks. CSS does not
>> define the
>> exact algorithm.
>
> The outer width of the div is not known until the shrink-to-fit width of the
> section is known,
> because the div's right margin width is unknown (since the computed value is
> ignored).
> Thus, the spec seems to allow assuming the right margin to be -10px, or
> really any other
> value, which then changes shrink-to-fit width of the parent.
>
> As a more pointed example: suppose the situation is as in my last email, but
> the
> div has a margin-right of -10px. Firefox renders the section as zero pixels
> wide in
> this case. On the other hand, without a margin-right of 0, the section is
> 10px wide.
> Both of these are the "intuitively correct" renderings, but according to the
> standard,
> the used value of the right margin is ignored, so why does it affect the
> rendering?
>
> (I agree that the renderings produced by browsers are correct, and also fit
> the standard.
> However, I cannot find where the standard does forces that rendering.)

You're jumping around a bit and applying some of the specification
algorithms incorrectly, or to the wrong elements.  I'm not sure
exactly where you've gotten confused, so I'll go through the example
in detail.

First, your code.  To make sure we're on the same page, here's the
markup we're working with:

<!doctype html>
<section>
  <div></div>
</section>
<style>
section { float: left; }
div { width: 10px; }
</style>

Right?  I'll assume that these are the only styles, so everything else
is the initial value according to the UA stylesheet.  I'll also assume
that the width of the window is 500px; the exact value isn't
important, but I'll need *something*.

So, I want to figure out the width of everything.  I first encounter
the section.  It's floating, so I use the rules in CSS2.1, section
10.3.5 <https://drafts.csswg.org/css2/visudet.html#float-width>.

The width is "auto", so its used width will be the shrink-to-fit
width.  To calculate this, I need to calculate the preferred width,
the preferred minimum width, and the available width.

CSS2.1 doesn't define the precise algorithm for preferred width, but
the gist is that you make the element *as small as possible* subject
to two constraints: (a) nothing overflows (unless it would overflow no
matter how wide the element is), and no inline content takes a
linebreak (unless it would break no matter how wide the element is).
(The Sizing module defines this in more detail
<https://drafts.csswg.org/css-sizing/#block-intrinsic>.)  The contents
are just a block box (the div) without any inline content, so only the
overflow condition matters, and that's easy to calculate - you can
shrink the section to 10px wide, but no smaller.

Minimum preferred width is similar, but you first cause linebreaks in
every single place you can legally do so, *then* find your smallest
width that avoids overflow.  There's nothing that can linebreak here,
so it's the same as the preferred width: 10px.

The available width *is* precisely defined - it's the width of the
section's containing block (500px) minus the section's
margin/border/padding (all zero), so it's 500px.

The the shrink-to-fit width is min(max(10px, 500px), 10px), which
resolves to 10px.  The section size is done!  You can now do the
"real" layout for the div, because you've now calculated the width of
its containing block (the section).  That's defined by 10.3.3, and
yes, we end up ignoring the margin-right of the box, but as it turns
out the solution to "0 + 0 + 0 + 10px + 0 + 0 + X = 10px" gives us
X=0, so no surprise there.


If the div had "margin-right: -10px", all the above still applies, but
the calculation of the minimum width that doesn't trigger overflow
changes.  Overflow happens when the *margin box* of an element is
wider than its container, and in this case the margin box is 0px wide
- 10px from width, minus 10px from margin-right.  So we can shrink the
section all the way to 0px without triggering overflow.  Then when we
actually calculate the div's size, we again ignore the margin-right,
but once again the answer that satisfies the equation is just its
previous value (-10px).


You are correct that CSS2.1 does not *fully* define this - as I said,
the preferred width calculation is not exactly defined.  The Box
module, unfortunately, is not up-to-date or relevant here, but the
Sizing spec does correct this lack and define things more precisely.
If you follow the Sizing rules, then the preferred width of the
section is "the largest max-content inline-size contribution of its
in-flow or floated children" (second paragraph of Sizing, section
4.3).  (The "preferred width" uses the max-content inline size; for
"minimum preferred width" you use the min-content inline-size, defined
by the first paragraph in 4.3.  See the glossary in Sizing at
<https://drafts.csswg.org/css-sizing/#max-content>.)  It's got one
such child, the <div>, and the div's min-content inline-size
contribution is 10px in the first example (it's got a definite width,
so the contribution is width + margin/border/padding) and 0px in the
second example (third paragraph of Sizing, section 4.3).  The

~TJ

Received on Monday, 7 March 2016 23:50:15 UTC