[css3-flexbox] Box-pack and equivalents

Alex brought up a good point regarding box-pack in another thread.

According to the current draft, box-pack applies at the very end of
computation, after all descendants have reached their maximum size.

In my proposal, it does the opposite due to me misreading this
section.  The equivalent of box-pack - putting padding on the parent -
occurs before the children are allowed to flex.  This is somewhat
inconvenient in some cases when a flexible length on a child doesn't
have a preferred size, and so doesn't claim any of the free space when
the parent is trying to flex its padding.

I immediately considered just reversing my first and second
distribution rounds to achieve the same effect.  However, this
produces some inconsistences when you next flexboxes.  If a flexbox
is, itself, a child of a flexbox, then its padding *must* resolve its
flexes before its children do, as it's part of the flex distribution
on its own parent.

Examples would probably help.  Assume this markup using the current
flexbox draft:

<div id=a display:box; box-pack:center;>
  <div id=b display:box; box-pack:center; box-flex:1;>
    <div id=c box-flex:1;>foo</div>
  </div>
</div>

And the intended equivalent in my proposal:

<div id=a display:flex; width:1000px; padding: 0 1fl;>
  <div id=b display:flex; width:1fla; padding: 0 1fl;>
    <div id=c width: 1fla;>foo</div>
  </div>
</div>


(1) In the current flexbox draft, you get a display like:

┏━━━━━━━━━━━━━━━━━━━┓
┃┏━━━━━━━━━━━━━━━━━┓┃
┃┃┏━━━━━━━━━━━━━━━┓┃┃
┃┃┃foo            ┃┃┃
┃┃┗━━━━━━━━━━━━━━━┛┃┃
┃┗━━━━━━━━━━━━━━━━━┛┃
┗━━━━━━━━━━━━━━━━━━━┛

It does this by following these steps:

1. #b determines its preferred width
  1a. It asks its children for their preferred width.  #c's preferred
width is the width of "foo".
2. #b then takes up all the space in #a.
3. There is no free space left in #a, so the box-pack has no effect.
4. #c determines its preferred width.  This is the width of "foo".
5. #c then takes up all the space in #b.
6. There is no free space left in #b, so the box-pack has no effect.


(2) In my proposal, on the other hand, you'll see this rendering:

┏━━━━━━━━━━━━━━━━━━━┓
┃      ┏━━━━━┓      ┃
┃      ┃┏━━━┓┃      ┃
┃      ┃┃foo┃┃      ┃
┃      ┃┗━━━┛┃      ┃
┃      ┗━━━━━┛      ┃
┗━━━━━━━━━━━━━━━━━━━┛

It does this by following these steps:
1. #a asks its children for their preferred widths.
  1a. #b's preferred width is the width of its content, #c.
  1b. #c's preferred width is the width of its content, "foo".
2. #a then figures out how much free space it has and divvies that up
between its two paddings.
3. There is no free space left for #b's padding or width to eat up.
4. There is no free space left for #c's width to eat up.


(3) If I reverse the first and second distribution rounds of my
proposal, though, then it produces:

┏━━━━━━━━━━━━━━━━━━━┓
┃┏━━━━━━━━━━━━━━━━━┓┃
┃┃    ┏━━━━━━━┓    ┃┃
┃┃    ┃foo    ┃    ┃┃
┃┃    ┗━━━━━━━┛    ┃┃
┃┗━━━━━━━━━━━━━━━━━┛┃
┗━━━━━━━━━━━━━━━━━━━┛

Because:
1. #a first lays out its children
  1a. #b asks its children (#c) for their preferred width (the width of "foo").
  1b. #a then collects the free space (100px - "foo".width, or, um, 12
spaces in the ascii art) and distributes it to #b's padding and width
2. There's no free space left over in #a, so no space gets given to the padding.
3. #b then lays out its children.  #a has a preferred width of 3
spaces, #b has free space of 7, so #a eats all of the space for its
width.

This is sorta crazy.  The order which padding on the flexbox is
processed depends on whether the grandparent understands flexes or
not.

So, I can't do (3), it's crazy and difficult to predict.  The question
is, which is most useful, (1) or (2)?  In (1) you can simulate (2) by
providing a max-width, while (2) can simulate (1) by providing a
min-width.

Alternately, (2) can simulate (1) through a separate property that
takes a flex length and evaluates it a separate distribution round
between the current round 2 and 3, so you wouldn't be forced to handle
the lengths differently based on whether the grandparent is a flexbox.
 You'd then write it like:

<div id=a display:flex; width:1000px; flex-pack: 1fl 1fl;>
  <div id=b display:flex; width:1fla; flex-pack: 1fl 1fl;>
    <div id=c width: 1fla;>foo</div>
  </div>
</div>

This would end up displaying things just like the current flexbox
draft does, because for both #a and #b all the free space is used up
before it reaches the new distribution round.

I don't particularly like adding a property that acts like padding,
only different, but I'm already planning to do that for between-child
margins with flex-spacing.  Shrug.

(Personally, I think the rendering for (2) is the best - it actually
*centers* things by squishing them as much as possible.)

~TJ

Received on Friday, 4 June 2010 22:46:25 UTC