Re: Fw: RE: [css-flexbox] Summary of planned changes to Flexbox Module

Well, turns out the algorithm for calculating flexes is remarkably easy.

All of this takes place during used-width calculation, after computed
lengths have been computed.  This algorithm is written in terms of
width, but can be used for either dimension with no change, since all
width/height dependent calculations happen before flexes are computed,
so we can be totally direction-agnostic in the algo.

0) Resolve all non-flexible lengths on the flexbox, and all non-auto,
non-flexible lengths on the flexbox children.
   Note that flex units are allowed in the padding of flexboxes even
if they are, themselves, in block flow or similar, rather than nested
inside of another flexbox.  For the purpose of this step, a flex unit
appearing in padding of the flexbox is treated as 0..
   (That is, given "<div display:block;><div display:flexbox;
padding:0 1fl;><span width=50%></span></div></div>", the inner div's
padding is treated as 0 for the purpose of determining its width in
the normal flow of its parent, and also for resolving the 50% width on
the span.)
   (I need to go into somewhat more detail here, to specify what the
min/max/fit-content width and height of a flexbox are.  It's a
relatively simple calculation - "as normal, but treat all flex units
as 0".)

1) Convert 'auto' widths and margins on flexbox children:
  a) If width is 'auto' and padding-left, padding-right, margin-left,
and margin-right are all not 'auto' and not flexible, the width is
treated as "1fl" for the purposes of this algorithm.
  b) Otherwise, if width is 'auto' it is treated as "fit-content", and
padding/margin-left/right values that are 'auto' are treated as "1fl"
for the purposes of this algorithm.

2) Collapse margins on flexbox children, if that margin is collapsible
(dependent on value of margin-collapse):
  a) Separate each margin into a flexible segment and an inflexible
segment (many margins will have only one or the other - in that case,
the missing segment is zero).
  b) The collapsed margin is then composed of 3 segments: an
inflexible segment, a flexible segment, and a flexible segment with a
minimum-size constraint:
    i) The inflexible segment is the minimum of the two inflexible segments
    ii) The flexible segment is the minimum of the two flexible segments
    iii) The flexible-with-constraint segment has flex equal to the
difference of the two flexible segments, and a minimum-size constraint
equal to the difference of the two inflexible segments

3) You now have a collection of flexible segments, some with
minimum-size or maximum-size constraints (min-width and max-width
specify constraints on the width's flexibility, if any), and a
collection of inflexible segments (any non-flexing widths, paddings,
margins, and borders).  The free space in the flexbox is equal to the
width of the flexbox minus the length of all the inflexible segments
and the minimum width of any flexible segments with a minimum-size
constraint.  If the free space is negative, set all flexible segments
to 0 length and exit this algorithm; the children will overflow the
flexbox in the direction indicated by box-begin.

4) If the flexbox is in a flow that does not allow flex units, but it
has flexible padding, distribute the free space among the flexbox's
padding in proportion with the flexibility of padding-left/right.
Reduce the free space by the amount of flex the padding has assumed.
   (If the flexbox is in a flow that allows flex units, then flexible
padding or any other flexible unit has already been resolved when
doing the flex computations of its parent, and so this step is
unnecessary.)

5) Distribute flex among flexbox children:
  a) Divide the free space up among the flexible segments in
proportion to their flexibility.
  b) If any minimum-size or maximum-size constraints are not
satisfied, set that segment to the minimum size necessary to satisfy a
minimum-size constraint, or the maximum size necessary to satisfy a
maximum-size constraint, and set that segment's flexibility to 0.
Return to step (a).
  c) If all constraints are satisfied, the algorithm is finished.


This algorithm does involve iterating until the flexibility
constraints are satisfied, but this should be acceptable.  The current
Flexbox spec requires the exact same iteration, and further, this
isn't iterative *layout*, since all the inflexible lengths the
algorithm needs can be calculated before this is run, and the layout
needs of grandchildren of flexboxes won't affect the variables that
this algo cares about.

I suspect linear programming may lead to a faster calculation of flex
distribution, but I don't know the subject well enough to say anything
about that.

It's important to note where flex units are allowed here.  Children of
flexboxes may use flex units in any of width/height/margin/padding.
Flexboxes themselves, if they are not in a flow that allows flex
units, may still use flex units in their padding only.  (If they are
in a flow that allows flex units, such as if they are themself the
child of another flexbox, then they may of course use flexes for any
of the dimensions allowed by that flow.)

Does anyone see any problems?  Any places where you think I've missed
an important case?  Any particular area you'd like to see in more
detail?

~TJ

Received on Friday, 14 May 2010 00:56:52 UTC