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-valueshttp://lists.w3.org/Archives/Public/www-style/2007Nov/0119.htmlhttp://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