W3C home > Mailing lists > Public > www-style@w3.org > February 2009

Re: Clarification needed for inline boxes containing block boxes

From: Andrew Fedoniouk <news@terrainformatica.com>
Date: Fri, 27 Feb 2009 11:24:52 -0800
Message-ID: <49A83E04.7020401@terrainformatica.com>
To: David Hyatt <hyatt@apple.com>
CC: Giovanni Campagna <scampa.giovanni@gmail.com>, Boris Zbarsky <bzbarsky@mit.edu>, www-style@w3.org
David Hyatt wrote:
> On Feb 27, 2009, at 9:02 AM, Giovanni Campagna wrote:
>
>> 2009/2/27 Andrew Fedoniouk <news@terrainformatica.com>:
>>> Boris Zbarsky wrote:
>>>>
>>>> Giovanni Campagna wrote:
>>>>>
>>>>> Can my text be the solution?
>>>>>
>>>>>> The resulting inline boxes should look exactly as they were 
>>>>>> contiguous
>>>>>> in DOM, but owned by different line boxes (ie with a line break 
>>>>>> inside
>>>>>> the inline box)
>>>>
>>>> I think so, yes.
>>>
>>> Could you explain then why these two spans should look
>>> so "dramatically" different?:
>>>
>>> <!DOCTYPE html>
>>> <html>
>>>  <head>
>>>    <style>
>>>      span div { border:1px solid; }
>>>      span { padding: 0 20px; background: green; border: 2px solid red }
>>>    </style>
>>>  </head>
>>> <body>
>>>  <span>aaa<div>bbb</div></span><br/>
>>>  <span>aaa<div style="display:inline-block;
>>>              width:100%;">bbb</div></span>
>>> </body>
>>> </html>
>>
>> Because they are different: one creates an anonymous a block box,
>> containing another anonymous block box, with a line box, with an
>> inline box, connected to the span; sibling of the second block box, a
>> new block is created, this time esplicitly, with line and inline
>> boxes; lastly: a new anonymous block box, with line and inline boxes,
>> the latter connected with the inline level element. That is, inline
>> boxes created by the inline level element "<span>aaa</span>" are not
>> ancestors of the <div> generated block boxes (this is not possible,
>> only block, inline-block, table-cell, column and page boxes can
>> contain other block boxes). They're not siblings either, because the
>> sibling of a block box can only be a block box.
>> Summing up boxes and associated elements:
>> -block --> anonymous
>>   -block --> anonymous
>>      -line
>>         -inline  --> <span>"aaa"
>>   -block --> <div>
>>      -line
>>         -inline -> "bbb"
>>   -block --> anonymous
>>      -line
>>         -inline --> "aaa"</span>
>>
>> As you see, properties set on <span> are completely unrelated to those
>> on <div> (apart from inheritance), so the background and borders are
>> not propagated to <div>
>>
>> The second example instead creates an anonymous block box (required by
>> the first example, otherwise it would have used the <body> block box).
>> Inside this box, initally a line box is created, that contains the
>> root inline box, generated by <span>, that in turn contains generated
>> by "aaa", then an inline-block for <div>, then another inline box for
>> </span> (created because of padding and margin, see CSS21 9.4.2).
>> This is therefore the initial box tree:
>> -block --> anonymous
>>   -line
>>      -inline --> <span>
>>          -inline --> "aaa"
>>          -inline-block --> <div>
>>          -inline --> ""
>>
>> Unfortunately, the line box is wider than the block box, so it
>> splitted into three line boxes as per normal line breaking rules.
>> Although CSS2.1 is not very clear about this, I expect that the
>> inline-block should be rendered as if it was an inline, replaced box,
>> with trasparent background.
>> Final box tree:
>> -block --> anonymous
>>   -line
>>      -inline --> <span>"aaa"
>>   -line
>>      -inline-block --> <div>
>>   -line
>>      -inline --> ""</span>
>> As you may see, in this example you only have one "block", and three
>> line boxes owned by the same block. This means for example that if you
>> set "line-height" on <body> (or a wrapping <div> that replaces the
>> anonymous block box), also the inline-block will move.
>>
>> I know, this behaviour is far from intuitive, but as Boris said, this
>> is what spec currently says and what browsers do. It's too late to
>> change.
>
> I find this topic really interesting, since right now WebKit does the 
> first approach (creating "before" and "after" anonymous blocks and 
> splitting the inline flows into these before/after blocks), and it's 
> horrible to deal with.  We call our implementation "continuations", 
> since the inline is effectively broken up into multiple objects.
>
> Pathologically constructed malformed Web sites create deep nestings of 
> inline flows.  When this happens, the act of splitting becomes very 
> painful.  It's O(n^2).
>
> https://bugs.webkit.org/show_bug.cgi?id=13430
>
> Disconnecting the inlines also leads to weird rendering bugs.  For 
> example try putting position:relative and a left/top offset on a span 
> that contains a div.  In WebKit at least, the span and its 
> continuations will move, but the block won't.  This happens because 
> the block is not actually a descendant of the span (or its 
> continuations) in the rendered object tree.
>
> I have been working on a new (more performant) implementation of 
> continuations in WebKit that would address both of the concerns I 
> raised above, and the approach I have been trying is kind of like the 
> second tree structure you've drawn above... i.e., create an 
> "anonymous" inline-block on a line by itself to hold the div.  That 
> way the span doesn't have to split.  I believe this approach could be 
> made to work, and pages that take 30+ seconds in other browsers load 
> in 3 seconds instead.  The major difficulty with the inline-block 
> approach is you still have to run margin collapsing with contiguous 
> blocks (including other contiguous "anonymous" inline-blocks) if the 
> inline content before or after the block doesn't exist.
>
> I guess my point was we should be careful about being too explicit 
> about how the rendered tree has to be implemented, since a literal 
> interpretation of the spec leads to pretty undesirable performance 
> characteristics.
>
> dave
> (hyatt@apple.com)
>
>
>
>
The problem can be distilled to this:

What exactly should happen if container element of
display-model: inline-inside (e.g. span) that has a child of 
display:block (e.g. div)?

I see only one reasonable solution in this case:

display-model (that is hypothetical attribute that used to be in drafts 
at some point[1])
has an absolute priority in this case and so all its immediate children 
with
display:block will have computed value of the display equal to 
'inline-block'.

This is pretty old problem actually. AFAIR Gecko and IE were using this 
way of treating display:blocks
inside inlines from the very beginning.

In general 'inline-block' value of the 'display' is superfluous. The 
only useful case
for the 'inline-block' is when it is used for determination of actual 
value of "width:auto" of such block.
In case of display:inline-block it gets resolved to width: max-intrinsic 
((c) D. Baron)
and in case of  display:block inside spans it gets resolved to the 
width: 100%-of-nearest
block-container-width.

For the observer this means that pure <div> inside <span> shall take 
single line box as
if that div was styled as {display:inline-block; width:100%}.


[1] "The 'display', 'display-model' and 'display-role' properties"
 http://www.w3.org/TR/2002/WD-css3-box-20021024/#L706

--
Andrew Fedoniouk.

http://terrainformatica.com
Received on Friday, 27 February 2009 19:25:39 GMT

This archive was generated by hypermail 2.3.1 : Tuesday, 26 March 2013 17:20:16 GMT