Re: [css-flexbox] min-width/height: min-content defaults for replaced items and overflow containers

On 04/22/2013 04:50 PM, Elliott Sprehn wrote:
> Recently the spec for flexbox was changed so that the min-width
> of flex items was no longer min-content (mutatis mutandis for
> height), but this produces some bad behavior when using replaced
> things like <button> or <img> as flex items. Previously they
> had an implicit min-width: min-content which would prevent them
> from becoming smaller, but now they'll end up being crushed.
>
> ex.
>
> <div style="display: flex;">
>    <img width="200" height="200">
>    <p>some long text that should wrap here</p>
> </div>
>
> In this example the <img> can end up being considerably less
> than 200px wide which isn't what the author intended.
>
> Before this change was made to the spec the min-width was
> min-content which worked fine for this but had other bad behavior
> like making overflow: scroll on a flex item behave unexpectedly
> since the item would expand out to the min-content size. [...]
>
> Both of these have proven to be surprising behavior, instead I
> think we should combine the behavior so the min-width is
> min-content unless your overflow property computes to a value
> other than visible in which case it should be 0.
>
> This special cased behavior gives a sensible result for <img>
> and overflow: scroll as flex items.

Overview
--------

So, this issue has been making me very uneasy about the resolution
we took in March about dropping 'min-width: auto', and I've concluded
that I would really like us to re-examine it.

I believe flexbox should generally "just work", and not do surprising
weird things. Clearly there were problems with the original definition
of 'auto', because it did weird things. But not having 'auto' also
does weird things. Imho the right thing to do is fix 'auto' instead
of dropping it.

Concerns
--------

These are the concerns on my mind:

   - Flexbox allows shrinking by default. It should honor intrinsic
     sizes such that things that have a definite size in the author's
     mind don't get squashed unexpectedly. (For example, Elliott's case
     should Just Work. At the very least, it should Make Sense, which
     it doesn't, really, in the ED.)

   - Relatedly, overflowing the flexbox with flex items is better
     than having the contents of flex items overflow into each other
     in order to make the flex items fit inside the flex container.

   - However, the contents of scrolly things should not be considered
     when sizing a flex item, because for scrolly things we don't
     really care how long the stuff is inside; that's the point of
     making it scrolly. This was Ojan's problem with the CR.

   - Don't confuse people by imposing the intrinsic size of something
     as its min-size when it's been explicitly sized to be smaller.
     This is also a problem with the CR.

Proposal
--------

Mostly as Elliott and Alexmog stated, but slightly different --
Reinstate 'auto', but change its definition to

   if (overflow != visible):
     min-width/height = 0;
   else
     min-width/height = min(min-content, width/height);

This makes 'auto' a little more magic than 'min-content', but gives
expected results more cases. If someone wants something else special,
they can ask for it by setting the min-size or flex-basis explicitly.

The only sensible cases that if-clause fails are:
   * wanting a min-content min-size when 'overflow' is 'hidden'
   * wanting a min-size smaller than min(min-content, size)
     when 'overflow' is 'visible'

Use Cases
---------

   Case #1:

     This was an original motivation for the min-size constraint.
     It protects against multiple overlapping flex item overflows
     when the flexbox is smaller than the author expected. (This
     would be a reasonably common and unnoticeable mistake, because
     authors generally don't check on small screen sizes.)

     <ul class="nav">
       <li>...
       <li>...
       ...
     </ul>

     As either a row or column flexbox, the CR version creates a stack
     of items that overflows the flex container:

     +=======================+
     |[ Item 1 ] [ Item 2 ] [ Item 3 ] [ Item 4 ]
     +=======================+

     Whereas the ED fits all flex items into the container, but
     causes their content to individually overflow the items and
     overlap:

     +========================+
     |[ It]m[1It]e[mI#]e[mI#] |
     +========================+

     Remember, the same problem applies to a vertical flexbox,
     even if you put a scrollbar on it.

      +------------+      +------------+
      | [ Item 1 ] |  vs. | ⁅#########⁆|  /* I can't ASCII-draw half-overlapped text. :( */
      | [ Item 2 ] |      | ⁅#########⁆|  /* Use your imagination.                       */
      +-[ Item 3 ]-+      +------------+
        [ Item 4 ]

   Case #2:

     Elliott's case.

       <div style="display: flex;">
         <img width="200" height="200">
         <p>some long text that should wrap here [... like a paragraph ...] </p>
       </div>

       +--------+
       | Image  |     +---------------------------------------...------------------...--+
       |        |  +  | some long text that should wrap here [... like a paragraph ...] |
       |        |     +---------------------------------------...------------------...--+
       +--------+

     Suppose the ratio of the image width to the text length is 1:19.
     In the current ED, if we put the image and the paragraph into a
     flexbox of size 500, the image will squash down to 25px by default.


        ++-------------------+        +--------+------------+
        ||... text ..........|   vs   | Image  |... text ...|
        ||.................. |        |        |........... |
        ++-------------------+        |        |............|
                                      +--------+------------+

     This is somewhat surprising given that images don't grow by default,
     and in an authors mind, are a kind of fixed-size element with respect
     to text-filled boxes and such things.

   Case #3:

     Hidden in Elliott's case is the distinction between intrinsic size
     and declared size. Suppose the image's intrinsic width is not 200px,
     but 400px, but the author declared its 'width' property as '200px'.

     If we use its min-content size as a minimum, its size floors at
     400px, not 200px, which is probably quite surprising to the author.
     Which is why the automatic minimum, if any, should not be greater
     than the specified size. This is a problem with the current CR.

   Case #4:

     Ojan's case.

       <div style="display: flex; height: 100%;">
         <div style="overflow: scroll;">
            ... thousand 100px tall items ...
         </div>
       </div>

     In the CR version of the spec...
     > The overflow: scroll <div> would end up being as tall as it's
     > min-content size which is the height of all the items and you
     > wouldn't get a scrollbar. Instead you needed to use min-height: 0
     > on the <div> to get your scrollbar to work [which has] proven
     > to be surprising behavior

   Case #5:

     A row flex item with user-generated flow content, including a large image.

       +---------+---------------------------------------+
       | sidebar |            main content               |
       +---------+---------------------------------------+

     * If min-width: min-content is implied (Flexbox CR), this could make
       the flex item too wide if the image is really wide, similar to how
       table-based layouts get messed up by such situations. This is, at
       least, a familiar problem and can show up on reasonably-sized
       screens if present, so will hopefully be noticed and handled by
       he author.

       <----------------- page size --------------------->
       +---------+-----------------------------------------------------+
       | sidebar | main content wraps to this wide.....................|
       |         | ......                                              |
       |         | [############### really wide image ################]|
       +---------+-----------------------------------------------------+

     * If min-width: zero is implied (Flexbox ED), wide content will
       overflow the flex item, either drawing under the next flex item
       (see Case #1) or drawing off the right edge of the page.

       <----------------- page size --------------------->
       +---------+---------------------------------------+
       | sidebar | main content wraps to this wide.......|
       |         | ....................                  |
       |         | [############### really wide image ################]
       +---------+---------------------------------------+

     In both behaviors, if the item contains significant flow content,
     an explicit min-width is recommended. For the CR version, to
     override the min-content behavior, and for the ED version, to
     provide a reasonable minimum. (Otherwise, as the flex container
     narrows to zero, content wrapping approaches dysfunctional,
     breaking at every opportunity.)
       http://www.w3.org/TR/2012/CR-css3-flexbox-20120918/#min-size-auto

   Case #6:

     A column flex item with user-generated flow content, including
     a large image.

     * If min-width: min-content is implied (Flexbox CR), too much
       content will cause flex items to overflow the flex container.

     * If min-width: min-content is not implied (Flexbox ED), too much
       content will overflow the flex item. This is generally worse.
       See Case #1 above.

I tried to extract cases from the original thread on this topic, but
there were no specific examples, just generalized complaints. :(
   http://lists.w3.org/Archives/Public/www-style/2013Feb/0364.html

Compatibility
-------------

MSIE10 implements an implied min-content minimum whenever min-size is zero,
so applications built on their flexbox implementation would already rely
on a min-content minimum. The cases that would experience a change are:
   * specified size < intrinsic size
       This is unlikely to cause a problem, more likely to fix one.
   * relying on min-content minimum while overflow != visible
       This is unlikely except in the case of 'overflow: hidden'.

Summary: Content built for IE10 Flexbox would need to change only if
          it relies on the min-content minimum taking effect on flex
          items with 'overflow: hidden'.

WebKit and Mozilla currently implement a zero minimum, so applications
built on their flexbox implementation might rely on the ability to
shrink below the min-content size. Since we are only changing behavior
where overflow is visible, the cases that would experience a change are:
   * relying on content's ability to visibly overflow the flex item
     without affecting its size.
       Pages generally aren't designed to use visible overflow, so
       this is mainly a change in "error" handling. It will result
       in better error-handling in some cases (Case #1, #6) and worse
       in others (Case #5).

Summary: Content built for Webkit/Mozilla Flexbox would need to change
          only if it relies on content visibly overflowing a flex item
          (and not stretching it).

Thanks for your consideration~ Congrats if you read through to the end! ;)

~fantasai

Received on Thursday, 18 July 2013 23:29:04 UTC