Re: Clarification needed for inline boxes containing block boxes

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)

Received on Friday, 27 February 2009 17:44:41 UTC