Open Bug 874238 Opened 12 years ago Updated 2 years ago

Implement fragment overflow feature from the CSS Overflow Module Level 4 spec

Categories

(Core :: Layout, enhancement)

enhancement

Tracking

()

People

(Reporter: MatsPalmgren_bugz, Unassigned)

References

(Depends on 1 open bug, Blocks 1 open bug, )

Details

(Keywords: css3, dev-doc-needed, feature)

Style system work: * add ::nth-fragment pseudo element style * add new 'overflow:fragments' property value * restrict which existing properties apply to the pseudo * deal with conflict resolution for 'overflow' 'display' etc Frame construction: * wrap all child frames in a fragment-frame initially * further restrictions on were it may apply? (XUL/tables etc) Layout: * make overflow create new fragment frames as needed, with style contexts matching ::nth-fragment(an+b)
Fwiw, the 'max-lines' property seems like it should live in css-break instead (together with 'orphan'/'widow') and apply to all fragmentainers? http://www.w3.org/TR/css3-break/#widows-orphans
Summary: Implement the CSS Overflow Module Level 3 spec → Implement fragment overflow feature from the CSS Overflow Module Level 3 spec
So I talked to Mats about this today. Some brief notes from my memory of our conversation: It seems like implementing this could be split into three parts: (1) implement overflow:fragments (2) do the layout pieces of splitting into multiple frames (3) implement ::nth-fragment() which is probably the best order in terms of being able to test as code is being written. On further reflection, (3) splits into: (3a) implement ::nth-fragment() applying to the fragments (3b) implement styling of content inside ::nth-fragment() and I think (3a), which is simpler than (3b), is needed for testing parts of (2). Further notes on the parts: (1) Implementing overflow:fragments behind a pref should work just like we used to have display:flex implemented behind a pref (though it's no longer behind a pref). (2) This is quite hard. There's a tradeoff between wanting a wrapper box around the fragments, which would make frame construction work easier but add complexity to reflow code in order to make it appear in all ways as though the wrapper isn't there is one option, but I'm not a big fan since I feel like we'd be catching error cases forever to try to get that "transparency" right. The alternative is to have no wrapper box, simply one box for each fragment. This involves a bit of complexity since in our current architecture we require the *container* to understand a child splitting. This would introduce the possibility of a child splitting in a container that doesn't expect it, or in a container that expects splitting to mean something else (e.g., line break or page break). It also, given styling, might mean that the different continuations of the fragment might need to end up in different child lists of the parent (some with a placeholder, some without; this might be more complex if the earlier one is a float and the next one isn't). Thus I think we probably want the splitting code to look more like calling back into frame construction to build the right things. We'd presumably want to store the current number of fragments in a property (probably on the content node, though maybe the frame) so that reconstruction of frames would repeatedly produce the right result. I'm not sure we'd be able to go do this reconstruction in the middle of reflow, though, which leaves a bit of a puzzle. There's a smaller problem to think about, though, which is implementing display:transparent (something that's "like" display:none, except its children get inserted where it would have been). We've had some discussions of this in the working group; I'm not sure if "transparent" is the current working name or not. I think it might be a worthwhile thing to try implementing this first, in a way that would extend to replacing the "transparency" with being multi-fragment. Either way, it probably involves serious frame construction changes, and we should definitely get bzbarsky involved. (We could have a three-way chat after I'm return to California on June 12th, or just Mats and bz before then.) (3a) Styling of fragments: When I was looking at this with Mats, I thought that the spec was a lot vaguer than it should be. But I've since found the paragraph that I was missing, which is: When determining the style of the fragment box, these rules that match the fragment pseudo-element cascade together with the rules that match the element, with the fragment pseudo-element adding the specificity of a pseudo-class to the specificity calculation. So we didn't get very far into this discussion, and also ran short of time. (3b) Styling inside fragments: Didn't get to this at all.
display:transparent on its own is not too bad to implement. Some general thoughts on it: 1) In the frame constructor, we'd just replace the relevant frame construction item with its kids in the frame construction list before doing any of the normal list processing. In fact, AddFrameConstructionItemsInternal could just do it directly when asked to add the items for the parent. 2) We'd probably need to double-check the interaction with the whitespace frame suppression bits. 3) We would need to replace GetFrameFor() calls in ContentInserted/ContentAppended/ContentRemoved/etc with something that walks up the tree past display:transparent things.... which means we'll need a way to flag the content nodes that need such walking past. Or something. Having style attached to frames sucks here. 4) We'd need to make sure that style reresolution for display changes from "transparent" to something else works. Perhaps via something like the undisplayed map. That might work for #3 too. 5) Obviously we'll need the "style parent frame" bits in style reresolution fixed, since the inheritance will need to happen from the display:transparent node... That might be a bit fun. 6) We'd need to ensure that we properly update the Bloom filter for selector matching when we descend into the kids of a display:transparent node during style reresolution; in particular we'll need to make sure the display:transparent node gets added in. Ccing Blake, since he's having a similar problem with xbl:children.
FWIW, the current working name for what I was calling display:transparent might be display:contents (at least among WebKit folks talking about it).
(I spawned off display:contents as bug 907396)
Depends on: 907396
I brief status update: I've implemented the overflow:fragments property, and the pref to enable it. I also have some experimental code implementing the :nth-fragment() pseudo-element in the style system, and some experimental code implementing splitting a scroll frame when it overflows. I'm trying to figure out how to apply the pseudo-element style to the frame but got stuck. I used ResolvePseudoElementStyle to get a style context for the ePseudo_fragment I added, giving it the current style context as parent, which seems to work, but using that on the scroll frame gives lots of assertions... I guess this has to be used on a different element/frame... The only way I see at the moment would be to wrap the *element* in an anonymous :fragment pseudo element and use display:contents on that (but messing with the content tree seems *wrong*). I don't really see how to make this work using two separate style contexts. <quote comment 2> When determining the style of the fragment box, these rules that match the fragment pseudo-element cascade together with the rules that match the element, with the fragment pseudo-element adding the specificity of a pseudo-class to the specificity calculation. </quote> Does this mean you see a way to have one style context that carries both the styles from the :fragment rule as well as the block? I think I need some guidance on the style system bits here...
Flags: needinfo?(bzbarsky)
Actually, I sketched up an idea on the plane back from the Summit that I'm hacking on now to see if it'll work... Briefly, for something like <body><div style="overflow:fragments"><p> the idea is that the <div> would have box:none and that anonymous ::fragment pseudo content nodes would be added so the content tree would look like: body div ::fragment 1 ::fragment 2 etc p and the frame tree: body ::fragment 1 p-1 ::fragment 2 p-2 the style context parent for the ::fragment style contexts would be the div style context, otherwise the same as the frame tree. Parenting p's frames under the frame for the "sibling" ::fragment content seems a bit weird at first but I think it might be possible to make that work. Let me know if you see any obvious problems in this approach.
That model seems to work quite well... the RestyleManager is making a fuzz about the ::fragment frames being continuations though, since they are for different content: ASSERTION: unexpected content mismatch: 'nextContinuation->GetContent() == aFrame->GetContent()', RestyleManager.cpp, line 1859 ASSERTION: continuations should have the same style context: 'aOldStyleContext->GetPseudo() != nextStyle->GetPseudo() || aOldStyleContext->GetParent() != nextStyle->GetParent()', RestyleManager.cpp, line 1865 ASSERTION: unexpected content mismatch: '!prevContinuation || prevContinuation->GetContent() == aFrame->GetContent()', RestyleManager.cpp, line 1796 That can be tweaked I guess, but I'm going to experiment with having the ::fragment frames not use the normal next-in-flow chain (to avoid violating current invariants), and instead use a new kind of continuation relationship. That will make the flowing between the ::fragments harder, but I expect some other things will be easier.
I have a question on how to setup the ::fragment style context - what's the best way to implement the "inherited by default" for all the properties? i.e. if I have div { overflow:fragments; height:100px; } div::nth-fragment(n) {} I want the ::fragment context to also have 100px height by default. (currently I'm faking it with an explicit "height:inherit") I suppose I could add to the UA sheet: ::nth-fragment(n) { *:inherit; } listing all properties ... but it seems this there must be a simpler way to do this in C++ that is more maintainable as we add new properties.
::nth-fragment(n) { all: inherit; } now that heycam has implemented the 'all' shorthand?
Keywords: feature
Flags: needinfo?(bzbarsky)
Hey, what's the status here? I see that there is a defendant story is completed, but I can't tell how much of the scope that solved. This story seems to have a massive/scary scope, so I'd like to break down what remains into manageable chunks. When this story was active (4 years ago) there was discussion whether the spec was ready/not. I have to believe it is by now. Also, does this still block max-lines, do we really need frame layout concerns to block text flow?
Flags: needinfo?(mats)
Summary: Implement fragment overflow feature from the CSS Overflow Module Level 3 spec → Implement fragment overflow feature from the CSS Overflow Module Level 4 spec
No longer blocks: 1232992
Depends on: css-break-3

The bug assignee is inactive on Bugzilla, so the assignee is being reset.

Assignee: MatsPalmgren_bugz → nobody

Clear a needinfo that is pending on an inactive user.

Inactive users most likely will not respond; if the missing information is essential and cannot be collected another way, the bug maybe should be closed as INCOMPLETE.

For more information, please visit auto_nag documentation.

Flags: needinfo?(MatsPalmgren_bugz)
Severity: normal → S3
You need to log in before you can comment on or make changes to this bug.