Open Loirooriol opened 7 years ago
This isn't a Display topic; it needs to be defined by the Flow Layout draft (currently Basic Box Model and severely unmaintained/outdated). But this is how the box tree should look:
<anon-block>
<anon-root-inline><span-inline>A<br>B</span-inline></anon-root-inline>
</anon-block>
<div-block><anon-root-inline>C</anon-root-inline></div-block>
<anon-block>
<anon-root-inline><span-inline>D</span-inline></anon-root-inline>
</anon-block>
(I've relabeled it to the currently-imaginary css-flow-1 draft, since Box isn't even in the labels system.)
So, when CSS Display says
In the course of layout, boxes and text runs can be broken into multiple fragments.
it does not refer to this case? The inline box is broken into different boxes (and not fragments), just as CSS 2.1 says? I thought CSS Display Introduction replaced that part of CSS 2.1
No, that's just a generic statement of something that happens for a lot of reasons. For example, a block box can produce multiple fragments if broken across a multicol boundary; an inline box is broken into multiple fragments if broken across a line.
@tabatkins, how is this particular case different from an inline box fragmented between two line boxes belonging to different column/page/region boxes? Aren't these fragments still parts of the single inline box? If yes, why should parts of the inline box belonging to different line boxes separated by a block-level box, but otherwise behaving the same (e.g. having no padding/border at the edge where breaking occured), be treated differently?
I'm inclined to consider all these cases as similar (if not the same) cases of inline box fragmentation. Maybe they should be covered in the CSS Fragmentation spec after all? Currently that spec is a bit contradictory regarding inline box fragmentation: first it says that it doesn't cover it at all, but then it still describes the box-decoration-break
behavior for inline box fragments as well. Maybe other aspects of inline box fragmentation (especially where other box types come into play) should be also covered there?
Agenda+ to ask a specific question. In the following scenario:
<span>inline <div>block</div> inline</span>
Is the div's block box a child of the span's inline box? (And then fragmentation causes the inline box to generate two inline fragments, one on either side of the block fragment.)
Or does block-splits-inline occur at the box-tree level, such that the span generates two inline boxes, siblings to the block box?
If the latter, which box is the span's principle box (or is it both)? This seems hard to observe, but I'm sure there are differences somewhere. More importantly, what matches browser internals most cleanly?
@fantasai and I think it's best if we go with the first option, where the span generates a single inline box (which generates two fragments), and the div generates a child block box. The other option seems... tricky.
@fantasai and I think it's best if we go with the first option, where the span generates a single inline box
Yes! Move all the hand-waving into the fragment tree and let the box tree be sane. I wrote my proposal in https://github.com/w3c/csswg-drafts/issues/1706#issuecomment-323552127
So in Gecko we don't really distinguish between boxes and fragments; they're one tree, and if we want to traverse boxes rather than fragments, we (a) ignore children that aren't first-fragments and (b) traverse children of later fragments. That said, block-in-inline and (in-progress) column-span splitting is a heavier type of splitting than breaking and bidi resolution, so there are contexts where we could mix the two modes (treat splits of inlines around blocks, and blocks and inlines around column-spans as separate objects, but not do that for bidi/line/column/page breaking), though I think we try to avoid it.
I worry that the proposal makes spec prose from CSS 2 that we still depend on even further from the truth than it currently is. In other words, we have prose that talks about boxes (at least when it remembers not to say elements) when it needs to be updated to talk about fragments -- if we change the definition of boxes to be less like fragments, future implementors may not realize that that prose was written before the distinction existed and think it means something different from what it actually means. If there were more of an ongoing effort to maintain that prose, this might be less of an issue.
That said, I'm also worried that drawing this distinction might force implementations to add new implementation concepts that they don't need now, just in order to get very minor details correct. It's often better for the spec prose to match what implementations do so that you don't get lots of very minor nonconformance. That said, I'm not sure what the other implementations do.
By the way, saying that the block generates a box inside the inline one explains the propagation of text-decoration
, i.e. "block" is underlined in this example:
<span style="text-decoration: underline">inline <div>block</div> inline</span>
This doesn't make sense if you only consider the fragment tree, but can make sense in the box one.
Gecko is able to do it properly despite having no box tree notion. So couldn't it use the same approach to handle the "very minor details"? I don't think implementations will be forced to add new implementation concepts.
It can become a substantial maintenance burden; I really don't want the spec's way of explaining things to deviate from implementations if the implementations are consistent and there isn't a really good reason to go the other way.
The mechanism that explains the propagation, by the way, is that in Gecko, the span gets split into three parts:
Having the anonymous block fragment is pretty useful for making sure pieces don't get lost when reconstructing boxes following dynamic changes to the DOM.
Though I believe text-decoration
propagation in Gecko actually uses the style tree which corresponds to the element tree, not the box tree. position: relative
is probably a better example.
@dbaron text-decoration
propagation should not happen in the element tree, see #1136 and https://bugs.chromium.org/p/chromium/issues/detail?id=553174
Yeah, pretty sure in Gecko it happens in the box tree. We rely on propagating them using a bit on the style for optimization. See https://searchfox.org/mozilla-central/search?q=symbol:_ZNK14nsStyleContext22HasTextDecorationLinesEv&redirect=false
(That is, we need to keep track of a bit in the style tree, but we compute decorations using the box tree)
text-decoration
is not actively propagated in Gecko. We collect the decorations via climbing the box tree (or frame tree in gecko's terminology) in each piece of text, as can be seen in nsTextFrame::GetTextDecorations.
The only (extra) thing we do via the style tree (element tree) is the optimization mentioned by @emilio, but that's just an optimization.
Blink does the latter in Tab's explanation, though it may change overtime. +cc @bfgeek
So it's actually two sibling inline boxes styled by default like fragments of the single inline box fragmented between two lines (and even reacting to box-decoration-break
the same way)?
Blink tree as of today is as below, though, we probably want to revisit this at some point. And yes to @SelenIT's question, the 2 spans are like fragments.
LayoutBlockFlow {HTML} at (0,0) size 800x96
LayoutBlockFlow {BODY} at (8,8) size 784x80
LayoutBlockFlow (anonymous) at (0,0) size 784x40
LayoutInline {SPAN} at (0,0) size 11x39
LayoutText {#text} at (0,0) size 11x19
text run at (0,0) width 11: "A"
LayoutBR {BR} at (11,0) size 0x19
LayoutText {#text} at (0,20) size 10x19
text run at (0,20) width 10: "B"
LayoutBlockFlow (anonymous) at (0,40) size 784x20
LayoutBlockFlow {DIV} at (0,0) size 784x20
LayoutText {#text} at (0,0) size 11x19
text run at (0,0) width 11: "C"
LayoutBlockFlow (anonymous) at (0,60) size 784x20
LayoutInline {SPAN} at (0,0) size 11x19
LayoutText {#text} at (0,0) size 11x19
text run at (0,0) width 11: "D"
LayoutText {#text} at (0,0) size 0x0
The Working Group just discussed How does block inside inline affect the box tree, exactly?
, and agreed to the following resolutions:
RESOLVED: In a block-in-inline split, the block is inside the inline in the box tree, and is a sibling of the two fragments of the inline in the fragment tree
RESOLVED: A multicolumn spanner that splits and inline is inside of the inline box tree and a sibling to the fragment in the fragment tree
I forgot that #1617 was a requirement. With the resolution above,
<main><span>A<div>B</div>C</span></main>
produces this box tree:
main: block box, IFC root
└ span: inline box
└ div: block box
(<main>
establishes an IFC because it only contains inline-level children.)
Then the fragment tree is
fragment of main
└ line box
└ first fragment of span
└ fragment of div
└ line box
└ last fragment of span
But this is wrong, a fragment of a box which establishes an IFC should only contain line boxes!
So we should say sequences of inline-level content directly contained in an element-generated block container are always wrapped inside an anonymous block container, which is what establishes the IFC. That is, element-generated block containers never establish an IFC.
Then the box tree is
main: block box
└ anonymous: block box, IFC root
└ span: inline box
└ div: block box
and this way the fragment tree ends up as desired:
fragment of main
└ first fragment of anonymous block
└ line box
└ first fragment of span
└ fragment of div
└ last fragment of anonymous block
└ line box
└ last fragment of span
I agree with the resolution. This issue could use the “Needs Edit” label as well.
So I suppose, the following markup:
<main><span>A<div>B</div>C</span></main>
According to CSS 2.1 (and css-inline-3), would produce this box tree:
main: block box
└ anonymous: root inline box
└ span: inline box
└ anonymous: block box
└ anonymous: root inline box
└ div: block box
└ anonymous: root inline box
└ anonymous: block box
└ anonymous: root inline box
With the resolution above, it would produce this box tree:
main: block box
└ anonymous: root inline box
└ span: inline box
└ div: block box
└ anonymous: root inline box
Is this correct?
The 2nd part seems correct. But CSS 2 didn't have root inline boxes, and inline boxes couldn't contain block-level boxes.
CSS 2.1 says
According to CSS Display Introduction, I guess now we would say the inline box is split into two box fragments.
But how does this affect the box tree? Is the parent node (in the box tree) of the block-level box still the inline box? Is the so-called "box tree" really a tree, or a more complex structure? Should we be talking about a fragment tree instead? Are box tree nodes in fact box fragments instead of boxes? Do these anonymous block boxes (the ones that enclose the line boxes before and after the break) really exist in the box tree, or do they only generate fragments in the fragment tree? Should this be explained in CSS Break?
For example, I think
generates fragments somewhat like
where
#1
is the inline box generated by the<span>
element#2
is the block box generated by the<div>
element#3
is an anonymous block box#4
is another anonymous block box#5
is the root inline box generated by#2
#6
is the root inline box generated by#3
#7
is the root inline box generated by#4
But how are
#1
,...,#7
themselves (not their fragments) structured in the box tree?