[css3-multicol] Intrinsic Widths of Multi-column elements (Take I)

I've been thinking about multi-col shrinkwrap wwidths a lot due to
the interesting situations we get into with vertical-horizontal
mixed text. I think it's not very well defined in the multicol
spec right now, and I'd like us to do better and solve some more
use cases, both for vertical text and for other things (some
situations Tab's coworkers were struggling with come to mind).
I also think we need to explicitly specify the min-content and
max-content widths, not just the fit-content (shrinkwrap) width,
since they are used independently in many layout calculations (e.g.
tables) as well as selectable via keywords on 'width' and 'height'
in CSS3. [1]

[1] http://dbaron.org/log/20080613-firefox3-css#new-width-values
     http://lists.w3.org/Archives/Public/www-style/2007Nov/0119.html
     http://lists.w3.org/Archives/Member/w3c-css-wg/2007OctDec/0267.html

I'll start by showing a couple examples of problems with the current
definition, to demonstrate that there's a problem we should fix. :)

Problems with the current definition of multi-col fit-content
=============================================================

The current definition of multi-col's fit-content width is
to use the fit-content width of the contents as the available
width. This results in some funny behavior.

Example 1:

|<-------------------width of containing block------------------->|
|This is a long but not too long sentence.                        |

The fit-content width here (as for floats, etc.) is

|<--------shrinkwrap width--------------->|                       |

If I set column-count: 2; column-gap: 2em; (represented by ##),
I get this:

|This is a long but ## sentence.          |                       |
|not too long       ##                    |                       |

Unless you're thinking about CSS layout algorithms, the result makes
no sense. It's based on a hypothetical calculation that has no basis
in any measurements used in the resulting layout.

Logically, I would expect maybe this:

|This is a long but not ## too long sentence.|                    |

or this (which is easier to calculate)

|This is a long but not too long   ## sentence.                   |

I'm not actually sure of the best way to define the layout here,
because I don't understand the use case for setting column-count
and asking for shrink wrap. But I think the result we get right
now is definitely weird.

Example 2:

Let's say I have a fixed height and a set column-width:

   height: 3em; column-width: 22ch; column-gap: 2em;

I have enough content to fill 2 columns. It would be nice if the
multicol element were sized to fit my two columns, like this:

| This is some content ## narrow columns like  |                  |
| ...                  ## this.                |                  |
| that fits into two   ##                      |                  |

But in fact, because the shrinkwrap width of the content is equal
to the available width, I get this:

| This is some content that would ## leave some room to spare, but|
| fit into two narrow columns and ## now we fill the block.       |

So I think we could use a slightly more sophisticated algorithm here.

Proposed Definition of Multicol Intrinsic Widths
================================================

There are three concepts of "intrinsic width" in CSS:
   the min-content width, which takes all possible line breaks;
   the max-content width, which takes no unforced line breaks;
   the fit-content width, which is defined as
                          max(min-content,min(max-content, available))

As the available width approaches infinity, the max-content and
fit-content widths become equivalent. (Max-content has sometimes
been explained as shrinkwrapping with infinite available width.)

In CSS2, the available width is always defined, even if it is big
enough that it is not used in the fit-content calculation. However,
this is not so in CSS3; sometimes the available width is infinite,
and instead we have an "available height", which is another concept
that doesn't appear in CSS2. (This happens when you place a horizontal
block inside a vertical block formatting context.) In such cases,
some substitute value must be provided to certain layout calculations
that need a definite value for the available width. This value, which
I will call the /fallback width/, and is currently defined to be the
size of the initial containing block.

Anyway. Now that we have all that defined up front, here's some
proposed definitions, Take I.

min-content width:
   Defined as the min-content width of the contents (same as now). *
   (Alternatively, define as the width of a multicol element with the
   column count and column gap as specified and the column-width as
   the min-content width of the contents.)

max-content width:
   If the used column count is 1, then the max-content width is the
   minimum of the max-content width of the contents and the used
   column width. *
   If the used column count is more than 1, then the max-content width
   is calculated from the used column width, used column count, and
   used column gap. **
   - If both column-width and column-count are set, these give the
     used column width and used column count. ***
   - If only column-width is set, the used column count is found by
     filling columns of exactly column-width, using any applicable
     height constraints.
   - If only column-count is set, the used column width is the
     maximum of
       - the min-content width of the contents and
       - the column width that results in a balanced columns
         height that most closely fits within any given height
         constraints, or,
       - if there are no height constraints, the column width
         that would be that would be calculated for a normal
         auto-width block (using the fallback width if the
         available width is undefined).
     ****

fit-content width:
   max(min-content,min(max-content, available))
   Equivalent to max-content if available width is not defined.

Use case notes:

   * This exception allows shrinkwrapping to the content, which is an
     important capability, especially for vertical-in-horizontal or
     horizontal-in-vertical situations. If the author wants a specified
     column width to be the minimum, he can set min-width to the column
     width explicitly. This definition makes both reasonable behaviors
     available.

  ** When there are multiple columns, they have equal widths even
     under shrinkwrap.

  ***This rule allows setting column-width and column-count explicitly
     and having "width: max-content" make the width depend only on the
     given column settings. Using "width: fit-content" then does the
     same thing except it maxes out at the available width, thus also
     preventing overflow.

****I couldn't think of a good use case for this situation, so I
     chose a behavior that tries to minimize overflow (content clipping)
     within the multi-col element and otherwise respects whatever
     constraints were given. The second condition (which tries to respect
     height when given) may be hard to implement, though.
     I'd be interested in what other people expect this situation to
     result in.

~fantasai

Received on Monday, 11 April 2011 21:35:23 UTC