- From: Andrew Fedoniouk <news@terrainformatica.com>
- Date: Wed, 04 Jun 2008 20:09:37 -0700
- To: dbaron@dbaron.org, www-style@w3.org
- Message-ID: <484758F1.6030800@terrainformatica.com>
L. David Baron wrote: > On Wednesday 2008-06-04 17:50 -0700, Andrew Fedoniouk wrote: >> Consider following markup: >> >> <body> >> <div>On the top</div> >> <div>On the bottom</div> >> </body> >> >> and we would like to "stick" second div to the bottom and first one to >> the top of the view. How would you >> accomplish that with XUL flexes? Probably I have missed something but >> that is impossible with XUL flexes. > > <body style="display:box; box-orient:vertical"> > <div>On the top</div> > <div style="box-flex: 1"></div> <!-- maybe needs 'display: box' ? --> > <div>On the bottom</div> > </body> David, I think you already know why this is bad. div in the middle is not a solution if we speak about CSS. > >> Flexibility is really a length unit rather than some property. > > No, since some layout models (traditional document layout) use one > dimension as input and the other as output; you can only flex in a > dimension that is input to the algorithm. In the existing CSS > model, in many cases, there is no sensible height that is input to > the algorithm (or, depending on how you look at it, multiple heights > that might be of interest). > I am not sure I understand this: "you can *only* flex in a dimension that is input to the algorithm" This <body><table width=100% height=100%></table></body> works perfectly well in Gecko as in other engines. (In html/table percents behave as flex units) So we already know how to flex things in both dimensions. That is why I am confused by your statement. Flexes defined in the context of some container. Content is measured normally (position:static) and if there is a free space left then this free space is getting distributed among all lengths having flex units - parts competing for free space. For inline-block elements container is a line box so this: <p>Input:<input style="width:1*; height:1*" /><br/> Input #2:<input style="width:1*; height:1*" /></p> will be rendered as: |Input:[~~~~~~~input~~~~~~~~]| |Input #2:[~~~~~input~~~~~~~]| Height if these inputs (height:1*) will be set to the height of correspondent line box. For containers that have display-model:block-inside flexes of children are computed against width and height such containers. For children of flow:vertical containers: width:auto, margin-left/right:auto are exactly width:1*, margin-left/right:1* - nothing new here. and height:1* and/or margin-left/right:1* declares this block as competing for free space distribution. If such container has declared height greater than intrinsic height of the content then it means that there is a free space. This space can be distributed among flexes. Flex distribution algorithm is simple. I've attached implementation that I use ( libra.h ). -- Andrew Fedoniouk. http://terrainformatica.com
//|
//|----------------------------------------------------------------------+
//| H-SMILE core |
//|----------------------------------------------------------------------+
//| Copyright (c) 2001-2008 Andrew Fedoniouk and |
//| Terra Informatica Software, Inc. |
//|----------------------------------------------------------------------+
//|
//|
//| Flex (Springs) distribution algorithm implementation.
//|
namespace html
{
class libra
{
public:
struct item
{
int vmin;
int vmax;
int v; // computed value
int p; // weight (>0)
};
int ptotal;
int vtotalmin;
int autos;
int freespace;
spring_engine()
{
clear();
}
void clear()
{
ptotal = 0;
vtotalmin = 0;
autos = 0;
freespace = 0;
}
// adds flex item to distribute
// param: valmin/valmax, min/max constraints.
// param: percent - weight
void add(int valmin, int valmax, int percent)
{
item i;
i.v = i.vmin = valmin;
if(valmax && (valmax < valmin))
i.vmax = valmin;
else
i.vmax = valmax;
i.p = percent;
ptotal += percent;
if (valmax)
++autos;
if(percent == 0)
vtotalmin += valmin;
add_item(i);
}
inline int val(int i) { return (head() + i)->v; }
// param: total, total container width to distribute.
// param: max100, flag - true - do 100%% normalization
// return: actual content width.
inline int calc(int total, bool max100 = true)
{
freespace = total - vtotalmin;
if(freespace <= 0 || ptotal == 0)
return vtotalmin;
item *start = head();
item *i = start;
item *end = tail();
int ptotalmin = ptotal;
if(max100)
{
if (ptotal < 100)
ptotal = 100; // key point
}
ptotalmin = ptotal - ptotalmin;
int save_ptotal = ptotal;
// worst case is n*n scans of the set.
for(item* iteration = start; iteration < end; ++iteration)
{
for(i = start;i < end; ++i)
{
if(i->p == 0)
continue; // skip elements having fixed size
if( ptotal == 0 )
{
//assert(false);
break;
}
int v = (freespace * i->p) / ptotal; // v, value - width candidate
if( v < i->vmin )
{
// minimum reached, exclude from distribution list
i->v = i->vmin;
vtotalmin += i->v;
save_ptotal -= i->p;
i->p = 0;
break;
}
if(autos && i->vmax && ( v > i->vmax ))
{
// maximum reached, exclude from distribution list
i->v = i->vmax;
vtotalmin += i->v;
save_ptotal -= i->p;
i->p = 0;
break;
}
i->v = v;
freespace -= v;
ptotal -= i->p;
if(ptotal <= ptotalmin)
break; //done
}
if(ptotal <= ptotalmin || freespace <= 0)
break; //done
ptotal = save_ptotal;
freespace = total - vtotalmin;
}
return total - freespace;
}
virtual void add_item(const item& it) = 0;
virtual item* head() = 0;
virtual item* tail() = 0;
};
}
Received on Thursday, 5 June 2008 03:10:25 UTC