Flexbox Implied Minimum Size

by fantasai

I would like flex layout to start from a reasonable layout interpretation of the content, and not do surprising weird things. Clearly, there were problems with the original definition of the implied minimum size of flex items, because it did weird things. But, because flex items are allowed to shrink initially, using zero as the minimum also does weird things.

I believe the right solution is to fix the definition of min-width/height: auto to be more intelligent rather than reverting it to zero.

Alternatively, we can consider making flex items inflexible by default.

The current proposal of allowing shrinkage and flooring at zero results in many common cases failing badly, often in situations the author isn't anticipating, and isn't particularly intuitive to fix properly either.

Concerns

These are my concerns that arose from this discussion:

Proposal

Based on suggestions by Alex Mogilevsky and Elliott, with feedback from Lea Verou:

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 in more cases.

If someone wants something else special, they can ask for it by setting the min-size and/or flex-basis explicitly.

Use Cases

Case #1: Preventing Overlapping Overflow

This was an original motivation for the implied minimum constraint. It protects against multiple flex items overflowing into each other when the flex container is smaller than the author expected. (This would be a reasonably common and unnoticeable mistake, because authors generally don't test on small screen sizes.)

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

As either a row or column flexbox, an auto minimum creates a stack of items that overflow the flex container, whereas a zero minimum fits all the flex items into the container, but causes their content to individually overflow the items and overlap:

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

Case #2: Crushed Images

This is Elliott’s case:

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

Sunshine is an emotional necessity for some people. This is why they don't live in Seattle, where it is only sunny for 3 months of the year. Other people are well-adapted to cloud-covered climates, and can therefore survive in such inhospitable climes.

Suppose the ratio of the image width to the text length is 1:14 and we put the image and the paragraph into a flex container of size 300px. If we use zero minimums, the image will squash down to 20px, whereas with auto minimum, the image will retain its intrinsic size while the paragraph wraps to its side.

Sunshine is an emotional necessity for some people. This is why they don't live in Seattle, where it is only sunny for 3 months of the year. Other people are well-adapted to cloud-covered climates, and can therefore survive in such inhospitable places.

Sunshine is an emotional necessity for some people. This is why they don't live in Seattle, where it is only sunny for 3 months of the year. Other people are well-adapted to cloud-covered climates, and can therefore survive in such inhospitable places.

Note in particular that in the zero-minimum case, the size of the image will depend on the length of the text, getting narrower as the text gets longer, even after it wraps!

This behavior 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: Intrinsic vs. Specified Size

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

If we use its min-content size as a minimum, its size floors at 120px, not 60px, 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.

img { width: 60px; }

Y u not 60px?

Case #4: Scrollable Boxes

This is Ojan's case:

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

With a min-content minimum (per Flexbox CR):

The overflow: scroll <div> would end up being as tall as its 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.

Let's suppose we have a fixed-height flex item (like a toolbar) below a flexible scroll-box...

.container { display: flex; }
.scroll { flex: 1; }

Case #5: Flex-item Content Too Wide

This is the flip side of Case #1. Consider a row flex item with user-generated flow content, including a large 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.

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) 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).