Re: [flex-units] unit abbreviations and the flex()

--------------------------------------------------
From: "Zack Weinberg" <zweinberg@mozilla.com>
Sent: Thursday, May 27, 2010 9:20 AM
To: "Andrew Fedoniouk" <news@terrainformatica.com>; "W3C Emailing list for 
WWW Style" <www-style@w3.org>
Subject: Re: [flex-units] unit abbreviations and the flex()

> "Andrew Fedoniouk" <news@terrainformatica.com> wrote:
> [re '1*' not being a DIMENSION]
>> Existing syntax just needs these two updates:
>>
>> PERCENTAGE ::= num '%'
>> FLEX                 ::= num '*'
>>
>> any        : [ IDENT | NUMBER | PERCENTAGE | DIMENSION | STRING | FLEX
>>               | DELIM | URI | HASH | UNICODE-RANGE | INCLUDES
>>               | FUNCTION S* any* ')' | DASHMATCH | '(' S* any* ')'
>>               | '[' S* any* ']' ] S*;
>>
>> I do not see any problems with this, do you?
>
> You're proposing a change in the CSS2.1 generic syntax.  I don't
> think that's worth doing just for the (arguable) additional
> readability of '1*' over '1fl'.

Any new unit type will be a change of CSS2.1 generic syntax.
E.g. 1pt is a LENGTH unit.  Adding either 1* or 1fl will require
change of CSS2.1 generic syntax.

Star notation of flexes like 1* is already used on the Web.
At least in html framesets.  Proposed flex units are *exactly*
that are used there. So any web developer can start using
them out of the box.

And take a look in Template proposal.  It uses flex units
in star form too:
http://www.w3.org/TR/css3-layout/#ltcol-widthgt

>
>> > I have no strong opinion on any of the rest of what you say,
>> > although I think that it would be better to arrange things so flex
>> > units can participate in calc expressions, than to introduce a new
>> > function.
>>
>> Full form of flex unit value is a triple of flex-strength, min and max
>> constraints. Additive flexes have one more "preferred" value so it
>> is a quadruple. I do not see any sense of trying to fit flexes inside
>> the calc() while anyway you know that you will need full form at
>> some point. E.g. you may wish to define something like
>>  border-spacing: flex(*, 0, 10px)
>> to implement  box-pack:justify in more configurable fashion
>> then you have in XUL at the moment.
>
> So I don't really understand either your "absolute flex" proposal, or
> the thing presently implemented in XUL that you call "additive flex"
> either.  What I understand is TeX's glue, which looks like this:
>
>  \hspace{10px plus 1fil minus 10px}
>
> That means: try to make the horizontal space here 10px wide, but if
> that won't work, it can be shrunk down to 10px-10px (i.e. 0) or
> stretched without limit.
>
> I had been under the impression that your '1*' in a CSS <length>
> was _exactly_ the same thing as writing \hspace{0px plus 1fil}.  Except
> that it can't be that simple, because you object so strenuously to what
> you call "additive" flexes, but to my mind, \hspace{10px plus 1fil} is
> a perfectly sensible thing to want ("make this no smaller than 10px,
> but it can be stretched without limit if necessary"), and
> calc(10px + 1fl) is exactly how I want to write that.  I don't care
> whether that fits into the existing semantics of calc(); those are not
> set in stone, they can be redefined so that it works the way it appears
> to work.
>
> (Now maybe \hspace{10px plus 1fil} is not what you mean by "additive"
> but then I have no idea what you do mean - please don't bother trying
> to explain it to me, though, this is really not what I need to be
> spending time on today.)
>

Ok. Let's try this. Consider this HTML construct:

<frameset col="100px, 2*, 1*">
    <frame #1 />
    <frame #2 />
    <frame #3 />
</frame>

I think you can easily visualize what will happen here.
And without any additional explanation, right?

frame #1 will be of 100px width.
frames #2 and #3 will take rest of the width of the container
(minus borders and spacing between them).
And yet frame #2 will be twice wider than #3.

I believe this clear and pretty obvious. Key point
here is that 2* and 1* are easily interpretable
by human - one element is twice wider than another.

Now let's try to define this layout in CSSish manner
and apply min-width constraints:

<frameset flow:horizontal >
    <frame #1 width:100px  />
    <frame #2 width:2* min-width:20px />
    <frame #3 width:1* min-width:20px />
</frame>

The frameset above has min width equal to:

100px + 20px + 20px = 140px.

So if container has available space less or equal
than 140px no flex computation is needed -
elements will have 100px, 20px, 20px widths.

Now let's assume that container is of 1000px
in width ( for the brevity let's assume that
borders and spacing are zeros).

frame #1 will get its legitimate 100px.
So we will get 900px to distribute among
flexible #2 and #3. Let's do it:

frame#2.width = 900px * 2 / 3 = 600px
frame#3.width = 900px * 1 / 3 = 300px

'3' here is a sum of all flexes.

As these two frames did not reach their
minimums we can use these computed
values.  And we've accomplished our
objective:  #2.width/#3.width = 2/1

And now consider that our container is
of  142px wide. And so #2 and #3 will
be replaced in 142px - 100px = 42 pixels;

Let's try to do this:
frame#2.width = 42px * 2 / 3 = 24px
frame#3.width = 42px * 1 / 3 = 12px

As you see frame#3.width is less than
its min now - it said to be "over-constrained".

To solve this we do this:
a) exclude its min-width from available space:
42px - 20px = 22px (new total space); and
b) exclude its flex value from total flex sum:
3* - 1* = 2* (new num of flexes);
c) exclude frame#3 from distribution as we
did with #1.

And let's run our computation again. At this
point list of flexible elements contains just frame#2
and its width will be:
  frame#2.width = 22px * 2 / 2 = 22px

And so we will have:
frame#1.width = 100px
frame#2.width = 22px
frame#3.width = 20px

frame#2.width will not be twice
wider as frame#3.width but still wider!

With those strange "additive flexes" frame2
may become even narrower than frame3.  I am not getting purpose of this
to be honest.

Actually I have published my implementation of
the algorithm above in this list already (couple of years ago or so).
It takes list of flex,min,max triplets and produces list of computed values.
The algorithm is finite and simple. Implementation is using only
integer arithmetic so is fast.

If needed I can repost it again.

> We run into a bit more trouble if we want to fit shrinkage into calc()
> (and I do) because "calc(10px + 1fl - 10px)" properly ought to be
> equivalent to "calc(10px - 10px + 1fl)" and thus to "calc(0 + 1fl)" and
> the bare "1fl".  I think what's needed here is a single-argument
> function shrink(), that goes INSIDE calc():
>  calc(10px + 1fl - shrink(10px)) :== \hspace{10px plus1fil minus10px}
>
> And for symmetry, let's also have stretch(), which lets us do this:
>
>  calc(10px + stretch(20px)) :== \hspace{10px plus20px}
>
> (i.e. "this can be anywhere between 10px and 30px wide").
>
> Is anything missing?  I find this notation much more pleasant than your
> proposal, under which I have to remember the order of arguments to
> flex().
>
>> In any case you will need to deal with possibility of
>> negative flexes like here
>>    calc( (10 - 10em/10%) * 1fx )
>> I do not think that Gecko as any other existing UI has
>> any room for implementing algebraic analysis of calc
>> expressions to split them on fixed and flex parts for separate
>> calculations.
>
> As I said to Tab some time ago, negative flex *per se* is not a
> problem.  It just makes stuff overlap, the same way negative margins do
> now.  \hspace{0px minus1fil} is a perfectly legitimate thing to write
> in TeX and would be useful in CSS under the same conditions (you want
> to paint something of uncertain width on top of whatever was on that
> side of it).
>
> I don't want to support "(10px - 10em/10%) * 1fx", but that can be
> excluded by dimensional analysis; no need for a full-blown algebra
> engine.  (Tangentially, I feel very strongly that dimensional errors
> within calc() MUST NOT be treated as syntax errors.)
>

This all appears as overcomplicated.

If you really think that \hspace{10px plus 1fil}  makes real sense
in CSS context then I think that flex() function that I've proposed
is simple and predictable. So that expression will be written
as flex( 10px, 1* ). No?

-- 
Andrew Fedoniouk

http://terrainformatica.com
 

Received on Friday, 28 May 2010 03:27:55 UTC