[css3-values] Why min() and max() are hard

I've been asked a few times why min() and max() are hard to
implement.

For a start, let me explain what they allow:  percentages normally
allow the CSS author to specify that a value (V) is some percentage
of the percentage basis (P) for that property.  For example, on
width, the percentage basis is the width of the parent element.
Thus, without calc(), percentages allow values to be linear
functions that intersect the origin, V = a * P, whereas lengths
allow specifying a constant, V = b.

With calc(), but without min() and max(), we extend this to allow
affine functions of the percentage basis, V = a * P + b.

With min() and max(), instead of these simple functions I believe we
would allow all continuous and piecewise-linear functions mapping
the percentage basis to the resulting value.  I think the algorithm
for constructing a min/max/calc expression for such a function
recursively works roughly like this (though as I note below, I
haven't worked out the whole thing and thus it doesn't constitute a
proof):
 * if constructing a linear function, construct based on slope and
   intercept, V = a * P + b.
 * otherwise, partition the function into a sequence of linear
   segments, split those segments at a segment boundary (though you
   need to be careful to pick one that works (i.e., where the
   extended segment doesn't intersect the other half), and I haven't
   worked out the right rule here, and thus haven't proven that this
   is possible), extend the segments at the split point straight in
   each direction, and construct the function min() (if the segment
   for values just below the split has larger slope than the one
   above) or max() (otherwise) with two arguments, constructing
   those recursively for each of the two halves of the split.

This means that it is no longer possible to find the percentage
basis that yields a particular result, since there may be none, one,
or many such percentage bases (and I don't know of an efficient way
to figure that out, either, though there may well be one).  This
type of computation is needed:
 * when computing the intrinsic width of a table from cells or
   columns that have a percentage width, which influence the width
   of the table in two different ways, as described in bullets (2)
   and (3) in
   http://dbaron.org/css/intrinsic/20110309#autotableintrinsic
 * when computing the intrinsic width of any element from margin or
   padding that has a percentage value (though for padding we
   already have this problem for calc() without min() and max(),
   since padding is constrained to be nonnegative)
It's actually important that things work this way because it leads
to results that don't have overlap/overflow, which is one of the
reasons for using intrinsic width calculation.  We could define an
alternative, but I don't see how to do so in a way that avoids
overlap/overflow.  At the very least, however, we should agree on
what alternative behavior is correct (and it should be one that
produces correct results without min()/max()) before encouraging
implementors to implement calc() and locking us in to a bad one.

-David

-- 
𝄞   L. David Baron                         http://dbaron.org/   𝄂
𝄢   Mozilla                           http://www.mozilla.org/   𝄂

Received on Tuesday, 25 October 2011 17:16:24 UTC