-
Notifications
You must be signed in to change notification settings - Fork 673
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[css-multicol] How do elements between column-span and its multicol ancestor appear around the span #1072
Comments
There doesn't seem to be any trace in the spec, but I am pretty sure we discussed this at some point during the last 5 years or so. I believe we had resolved to make column span only apply to direct children of the multi-col rather than arbitrary descendants to avoid this exact problem, and due to the lack of use case presented in favor of allowing it. The creation of display:contents since then makes an even stronger case for that solution, as you can get rid of unnecessary wrapper elements. |
That said, maybe not. In a document with an old fashioned structure with multiple levels of headings and paragraphs all sibling of each other, then that argument may work, but with a more structured outline and nested sections, you are fairly likely to want a multi-col on a article, nest section elements in it, and want to span a heading that is a child of a section (or of a header element. I can reasonably imagine either spanning the header element instead of the h1 it contains, or applying display:contents to it, but that does not work nearly as well on the section element. |
In Blink, column content is completely interrupted by a column spanner (which is non-column content). It's similar to how blocks inside inlines behave, i.e. by interrupting them. Column content (whether it's block or inline doesn't really matter, I think?) and spanners don't interact (apart from a spanner finishing and balancing the preceding column row). No column content border/background is painted in the area occupied by the spanner. Also, the containing block width of the parent of the spanner doesn't matter. What matters is the size of the content box area established by the multicol container (measured before it's divided into columns, obviously). For this to work sensibly, we cannot just allow any kind of ancestry between the spanner and the multicol container. The spec requires that parents do not establish new formatting contexts (I think we should disallow establishing any kind of formatting context, such as tables or flexbox - and this is what Blink does.). Then, how about relative-positioning and transforms? The most sensible thing would be to let spanners be affected by such parents, right? Or, alternatively, disallow spanners inside such ancestry. Blink ignores offsets caused by relatively positioned parents, FWIW, but I'm inclined to consider that to be a bug, seeing that this is not how blocks inside relatively positioned inlines work. In Blink, column rows and column spanners are effectively siblings. The containing block of a spanner (and of a column row, really, but they don't have a DOM node, so kind of irrelevant perhaps) is always the multicol container. |
Discussed on the call - there was some interest in simplifying to make column-span apply only to direct children of the multicol element. But there was also concern about headings nested in sections and similar use cases. It would be good to find out what browsers do and do not handle a nested heading, and have some test cases added to the test suite. |
Tested this on different browsers and posting results with screenshots: Test case: https://jsfiddle.net/5oo2gzLy/8/ Tested on: Description:
Observations:
Screenshot for Safari showing extra line with no background:
|
So implementations seem to agree with what Morten said should happen in #1072 (comment), at least in the block case. In the inline case, only safari disagrees, and I have a hard time seeing how that's useful. Can we agree that:
|
It's probably also worth testing an example with 'position: relative; left: 100px' to see if the spanning element moves left with the relative positioning of the ancestor that it breaks, similar for a 'transform', and probably also something graphical like 'filter'. But if all implementations are acting like those elements aren't around the spanning element in those cases as well, then we should probably just stick with that approach. |
Here are the screenshots for applying relative positioning, transform and filter to the parent of the column span. In most cases (except transform in chrome shown below), the column-span itself seems unaffected by these changes but apart from that there is a lot of variation so I'm posting almost all the screenshots - 1. Adding Position: relative; left: 100px; 2. Adding transform: rotate(90deg); 3. Adding filter: grayscale(100%); |
Another piece that needs to be defined is the definition of emptiness for a fragment of a block or an inline that is split by a
under what conditions do you see pieces of the border/background of the div before the h2? Are the rules different for blocks and for inlines? Are the rules different for inlines split by a It's also worth thinking about the fact that a single inline element might be split both by a block and by a |
I would hope that this would fall out of the rules in css-break, doing the same as if you had a forced break where the <h2> is, which is effectively what's happening here. |
Looking at the spec, it does not seem that this behavior is invoked, even implicitly. Do you think it would this clarification would work? changing in css-multicol's definition of
to
I think this would give us a sane and consistent model. Casual testing indicates this does not seem to match what existing implementations do, but then again implementations do not seem to match each other closely either, so I do not know if we need to be bound by compat here. |
An added benefit of defining things this way is that it would make clear what happens to the bottom margin of a element immediately preceding the spanner and the top margin of an element immediately following, since they would be adjoining a forced break, and what happens then is defined. We would probably need to add normative prose supporting the claim made in example 25 that when the spanning element itself is the first thing after an unforced page break, its top margin is truncated. I guess we could do that by clarifying that the forced break is on the place holder left in flow after taking the spanning element out of flow, not on the spanning element itself. I guess something like this:
|
This issue was discussed in March on the call (before links were posted to github issues) so adding a link to the minutes here: https://lists.w3.org/Archives/Public/www-style/2017Mar/0037.html Is there any additional feedback at this point? |
The Working Group just discussed
The full IRC log of that discussion<eae> Topic: column spanning issues<eae> github issue: https://github.com//issues/1072 <eae> rachelandrew: Three issues all referring back to each other. Main issue is 1072. Propose we resolve it first and then refer back to it. <eae> rachelandrew: Quite a long issue. dbaron raised it and florian commented quite a lot. <eae> rachelandrew: Quick summary: When you got an element with column spanning and they're not a direct child of the multicol box container and they're still spanning. The definition says what happens to the ancestor. A good example would be a section with headings and one of them has span all. <eae> rachelandrew: Was discussed on a call in May, June, and then went back to discuss on github and then stopp.ed <eae> rachelandrew: Perhaps we shouldn't allow these nested things to span. <eae> fantasai: There was some comments on allowing nesting of block but not things within another formatting context. Seems like a reasonable compromise. <eae> fantasai: I don't think it is particularly useful for it to pop out as long as regular block elements work. The restriction makes sense from a behavior and implementation point of view. <eae> fantasai: It is what I'd expect to happen it it makes what implementations seem to do. Makes sense to specify that behavior. <eae> rachelandrew: I'd be happy to draft that up, makes sense to me. <eae> fantasai: Happy to review spec text. <eae> * discussion about florians comment in issue 1072 * <iank_> https://github.com//issues/1072#issuecomment-299097552 <iank_> ? <eae> fantasai: Arbitrary depths but you cannot cross a formatting context. <eae> fantasai: Header inside a section is a good example. <eae> Proposed resolution: Column span applies to elements lower than the first level of decendence as long as it doesn't cross a formatting context <eae> RESOLVED: Column span applies to elements lower than the first level of descendants as long as it's part of the same formatting context. |
The Working Group just discussed
The full IRC log of that discussion<eae> Topic: Background and borders for spanners<eae> github issue: https://github.com//issues/1072 <fantasai> https://github.com//issues/1072#issuecomment-299076034 <eae> fantasai: What if the spanner is the very first element in an element that has borders and margins and paddings? <eae> fantasai: Is the top margin pushed to after the spanner? <eae> fantasai: For an inline what florian suggest in the issue that would be broken, what would we do in that case? <eae> rachelandrew: I'd like to see what implementations do at this point. Heavn <eae> 't looked at that <fantasai> http://software.hixie.ch/utilities/js/live-dom-viewer/?<!DOCTYPE html>%0A<span style%3D"border%3A solid%3B">%0A <span style%3D"display%3A block">splitblock<%2Fspan>%0Arest of text<%2Fspan> <eae> fantasai: Here is an example with a block splitting an inline. You can see that the border and then the split inline. <eae> fantasai: There is a lot of fragmentation bugs as well. Entirely separate pile of "fun". Right now we're only dealing with the multicol aspects. What are the implications for this split. <eae> * fantasi gives an example with spanners and multicol and borders * <eae> iank_: What appears if the spanner is the first child? What do you want to appear before the spanner? Maring border padding? <eae> fantasai: Yes <eae> iank_: Makes sense <eae> fantasai: I don't know if I want that but it is what would fall out from it being analogs <eae> s/analogs/analogous/ <eae> Rossen: The example is having a section inside an element with border? <eae> * fantasi draws an example * <eae> fantasai: We have a multicol with some stuff and a section element, then we have an h2 and the h2 is a spanner. <eae> fantasai: The section has a border <dbaron> The in-progress Gecko implementation treats it as analogous to block-in-inline splitting. <dbaron> although it's a little harder in a few ways, and a little different in others. <eae> fantasai: We definitively have a border around the section. The question is where the border goes. <eae> fantasai: Remember the header is inside the section. <eae> fantasai: First piece of border is before the split. Then you have the block and then the border continues. <eae> fantasai: If that is bad behavior we could say that this fragment doesn't exist and then ... <eae> * these notes makes no sense without the visual of the example... * <eae> Rossen: For the purpose of margin collapsing, When we take the spanner out of the element, the right element, asusming it was the only content, then margin collasoing with the red border would change. <eae> Rossen: If the element is effectively taken out of the flow of the containing blocks flow and then I don't see a reason why this element would be breaking the position of the top border of its parent. <nainar> Board images: https://photos.app.goo.gl/sm5cc7q8pywbSF0P2 <eae> Rossen: Now that the spanner is outside of the containing block and margin collasping would change, the red box in the digram could be pushed further down due to margin collapsing. <eae> florian: So you're saying it would normally be posioined here but there being no margin between them there would be no space between them and the margin would not be in between. I think that is a pretty good point, arguing for leaving it up here. <eae> s/florian/fantasi/ <eae> rachelandrew: It is little weird, if that was one line of text up there it is still odd. <jensimmons> q+ <eae> iank_: Effecitvely the spanner is treated as out of flow positioned? <eae> Rossen: Yes, pulling it out of flow is getting tricky. We're there already <dbaron> Reading the IRC, this doesn't make any sense to me. <eae> iank_: That would mean that margins would collapse though it <dbaron> but I don't know what people are pointing at. <eae> o <dbaron> I also suspect you haven't even gotten to any of the interesting issues yet... :-P <jensimmons> hey, is what I just said getting noted? <jensimmons> seems like a lot of this conversation is being missed, sadly <TabAtkins> ScribeNick: TabAtkins <eae> fantasai: I think rossens argument about the marign collapsing bebehvor this is confusing. The margin top is never going to be between the header and the first paragrapgh. If we go with the behavior where the top fragment doesn't exist then the margin is between the header and first paragraph. Then why is it above the header? <TabAtkins> fantasai: That for me is the compelling argument to not do anything. <TabAtkins> jensimmons: I can see a use-case where section>h2>content is the proper markup for content, and for small viewport sizes it's styled one way, and for large it's done in this diagram style <bradk_> does box-decoration-break apply to the first fragment above the spanner? <TabAtkins> jensimmons: I think it's fine if we let it break <TabAtkins> rachelandrew: I think so too. Just need a resolution for that so it's tied to the spec <TabAtkins> fantasai: I think this is a common situation, just question of where to draw top mbp; it goes above the header <TabAtkins> rachelandrew: Happy with that. <TabAtkins> RESOLUTION: If the fragment before the spanner is empty, nothing special happens; the top mbp is above the header, and it's just an empty fragment. <fantasai> s/RESOLUTION/RESOLVED/ <fantasai> ;) |
…rs and their containing block #1072
The CSS Working Group just discussed
The full IRC log of that discussion<astearns> topic: column-span<emilio_> github: https://github.com//issues/1072#issuecomment-465362932 <emilio_> rachelandrew_: it's a reopened issue that was resolved on but dbaron reopened requesting some clarification <emilio_> rachelandrew_: the example is figure 11 in the spec <emilio_> rachelandrew_: the initial thing was mentioned was essentially a clarification. The situation is when margins paddings and borders are split by the spanner, but an empty fragment ends up before the spanner <astearns> s/11/21/ <fantasai> I think this just needs to adopt the same wording as CSS2.1 block-in-inline splits <emilio_> dbaron: a bunch of the clarifications was just to say what happens for elements that are both descendants of the multicol and ancestors of the spanner when they're split by the spanner <emilio_> dbaron: a more interesting is what happens when there's an explicit height and how's it distributed <emilio_> fantasai_: simplest is to treat the split as creating a fragmentation break, but computes padding borders as if the spanner didn't exist <Rossen> q? <emilio_> dbaron: I think everyone pretty much agreed with the outcomes even if there's disagreement on how to describe them <emilio_> florian[m]: there are a couple related aspects <emilio_> florian[m]: <section><div><aside><span>splitted element <emilio_> <section><div><aside column-span: all> <emilio_> florian[m]: We thought it could be described like the spanner being oof <emilio_> florian[m]: but forces a fragmentation break <emilio_> florian[m]: so that it doesn't influence min-content and such <emilio_> florian[m]: the div is not affected by the span itself <emilio_> florian[m]: I think it's easier to define the span this way <emilio_> rachelandrew_: I think it's one of the cleanest way to describe it <emilio_> rachelandrew_: and easier to understand <emilio_> fantasai_: I think out of flow stuff in CSS is taken out of the flow, the rest of the stuff is supposed to ignore it. an oof span in a paragraph doesn't cause a break on the parent <emilio_> florian[m]: it's not quite true that oof don't affect the float -> floats <emilio_> florian[m]: we need to define the specifics, but other than that is out of flow <fantasai> emilio_^: actually, it leaves behind a break opportunity <fantasai> emilio_: At least in Gecko, Webkit and Blink, out-of-flows do create break opportunities. I believe it's a bug. Edge does it right. <fantasai> florian: In this case it would be a forced break rather than a break opportunity <fantasai> Rossen: This is the model we use in Edge. We treat it as out-of-flow and force a break <emilio_> Rossen: this is the exact model we use for spanners in edge <emilio_> AmeliaBR: is probably worth referecing it as being similar to a flow wrt. background painting order and co? <emilio_> rachelandrew_: yeah I think I should write some spec text <emilio_> RESOLVED: Clarify the spec using the notion that this is an out of flow that leaves a forced break behind |
"Out of flow" is probably not the right term to use in the spec though, since that might mislead people to think that it's "positioned", which means it's an absolute containing block, paints in a separate layer from in-flow content etc. which would be wrong, IMO. |
Are floats necessarily positioned? |
No, but floats also paint in a separate layer from in-flow content (step 5). I think it would be more accurate if the spec introduced a concept of abstract "rows" to describe this. The spec can then say that
|
See also my multicol model suggestion here: |
Yeah, I completely agree that @mstensho 's model in that comment is the right one, and very strongly advocate that it be folded into the spec, as the CSSWG resolved. The only question here is about how we capture the way that it's taken out of the columns' fragmentation flow and formatted as a sibling of the column row boxes. Initially the idea was to treat it as a block-in-inline split situation; however dbaron was arguing it should be out-of-flow because then there doesn't need to be some abstract tree structure representing all of the boxes between it and the multi-column container, since that's complicated to implement. I think either concept is good enough, but yes, we should be clear about the effect on the painting order. Probably column spanners should interleave with the row boxes the same as other in-flow content; I guess its an interesting question whether they should form a pseudo-stacking context (like inline blocks) or behave like regular block boxes. |
@MatsPalmgren @emilio Floats aren't “positioned” since that's not a defined CSS term... They are out-of-flow, and they are not absolutely-positioned. |
We have already resolved to add @mstensho's model. I just haven't done the edits yet. The issue with the concept of rows is how that impacts our intention to enable multicol overflow in the block dimension for continuous contexts. That's something I'm very keen to move forward on in Level 2 as it would actually make multicol useful on the web. Personally, I think that describing the spanner as out of flow makes a lot of sense, it's something I could teach to people. It needs describing properly in the specification in terms of what the impact is. Now I'm less busy I'll have a crack at that. |
@fantasai Right, my point was that out-of-flow is not anything exclusive to positioned elements. Also I didn't realize that floats and abspos are completely exclusive (if you specify both, float becomes none at computed value time). |
So I'm working on editing in @mstensho's model along with this resolution. What I have is a problem of naming things. We resolved to name the element which has In @mstensho's model we end up with an anonymous wrapper, which he has referred to as a multicol container. Initially I thought we could refer to this as "rows", but having discussed this in SF with @frivoal we are both keen to keep rows for the scenario when we allow for overflow in the block dimension, which would create (in the mind of the author) very definite rows of column boxes, which could themselves contain spanners etc. I think row should be maintained for this use. So, what do we name the anonymous wrapper? We could use multicol wrapper. In the flexbox spec we have flex lines, so multicol lines? Does anyone have a better suggestion? |
Well, it is something that contains one or more rows with columns (and nothing else). So, why not just simply "row container"? I don't think I quite understood the reservation against using the term "row" here, since that's the term that the spec already uses for this. |
What would we then name the rows created by block overflow, given that they themselves could contain row containers of column boxes along with spanners? We've changed other terminology in this spec already (multicol container), I'd like to make sure we aren't causing difficulties with a highly likely future addition. |
"rows created by block overflow" - is this somewhere in the overflow spec, or what exactly is this about? |
as mentioned above:
|
Would this be a mode where you effectively (kind of) want to pretend that we have columns:1 and a definite block size? In that case, overflowing content will be placed into additional fragmentainers, wouldn't it? No rows involved, as far as I can understand. But if this in a draft somewhere, maybe reading that could enlighten me. |
This isn't in a draft anywhere yet (although I have some private notes scattered around), but we've been discussing the possibility of introducing some kind of switch to decide what to do with excess content when you've filled you allotted (max) width and (max) height. It'd allow authors to pick between the current behavior (excess content goes to overflow columns appended in the inline progression direction), and a different one where excess content would append a second "row" to the multi-column, in the block progression direction (possibly based on some kind of article {
columns: 3 20em;
column-height: 80vh;
column-which-way-do-I-go-when-I-am-full: block;
gap: 1em 2em;
}
Regardless of exactly how that ends up working, something along these lines has been brought up multiple times, and it'd be good to avoid painting ourselves into a corner. In that sort of model, we have two things that could reasonably called "rows":
To some degree, for the current issue, we can do whatever we want, because we're only introducing internal terminology that won't be visible through any property/value/API..., but if we could get sensible names from the get go, that'd be great. At first, I'd tend to call (1) "rows", and to call (2) "row groups". However, if we want to make things like the So if we call (2) "rows", what do we call (1)? "lines" for the analogy with flexbox lines? "group"? "set"? "line" probably feels the best suggestion so far to me, I'm not sure. |
I really would like to reserve rows for (2) in @frivoal's example above. I think that it is what authors will tend to think of as a row, and It seems that this other box, needed for the model we are trying to introduce, probably isn't something authors will worry about. I also like lines, it seems to work as I've been noodling at drafting this. |
Thanks. Now I get it! :) Would it make sense to spec it in such a manner? We might still want some terminology for the outer fragmentation context. The fragmentainers it generates aren't columns, and not quite pages, either. Or? This is similar printing a multicol container that gets split into multiple pages, or, even more similar to how Presto (Opera) did paged overflow, where you could also get two fragmentation contexts established by just one element. There used to be some documentation somewhere at opera.com for this, but I can't find it anymore, but essentially:
The DIV would establish an outer (paged) fragmentation context and an inner (multicol) fragmentation context. We'd fill columns in the inline direction until we run out of space, and then we continue to the next page and establish a new row of columns there. And so on. While that solution was less flexible than what you're presenting here (for one, the Presto solution forces you to put everything inside a scrollable container), it's essentially the same, isn't it? But does multicol necessarily have to be a part of this? E.g.:
(pretty obvious that the property name 'column-height' wouldn't be ideal, though)
We may call the first fragmentainer (with lines 1-4) one row, and the second fragmentainer (with lines 5-6) another row. But they no longer have anything to do with columns. So there'd be no naming conflict. We have table rows, column rows, and this new thing, that's a different kind of rows (inside a still unnamed type of fragmentation context) - related to fragmentation, but not to multicol. And if we want to support row-gap, that would apply to the outer fragmentation context, and not to column rows created before/after spanners. |
Warning: this is a bit of a side track, but it's kind of useful to discuss why the thing discussed in #1072 (comment) is on the horizon if we want to use its probable existence as a justification for how we should name things. What you're describing in #1072 (comment) is different mechanism that we're also of exploring, and which does have with some degree of lineage to the opera paged overflow you mentioned. A very rough outline of how that might work is in https://drafts.csswg.org/css-overflow-4/#fragmentation, and clearer details about first steps towards that are in https://drafts.csswg.org/css-overflow-3/#fragmentation. In this, However, while this is more powerful because it can apply not just to multicol, but also to all sorts of layout systems, it's also way more complicated than something specific to multicol. The thing I described in #1072 (comment) wouldn't really need to be thought of as nested fragmentainers: the columns are the only fragmenting things, and the only question is where we place them. They're either arranged in 1d as today, or this proposes laying them out in 2d, but from the point of view of the content in it, there's no nesting going on (spanners make that a bit more messy, but not that much more messy, so I won't get into that here). Somewhere around 2012 (at least at the Hamburg F2F), we briefly considered this, and similarly to the comment you made above, though that it wasn't needed because we could use some kind of nested fragmentation on demand, or css-regions (which were still a contender back then). But time has since proven that going that way was much harder, and multicol is still without a reasonable solution for being useful in continuous medium. Since then, we have also developed, via flexbox, grid, and css-alignment a set of concepts and properties that would readily apply to this kind of 2d layout of columns. I do expect that we'll eventually solve the problem of generic on-demand fragmentation (and I'll be pushing for it), but I now want the multicol-specific thing as well, and hope to push for it soon. I believe that quite a few people are interested as well. Of course I can't know before we do it that it'll work out, but if we can pick internal terminology that doesn't make that project more confusing than necessary, that'd be good. |
The definition of
column-span
doesn't appear to say anything about what happens to the elements that are ancestors of the element withcolumn-span: all
but descendants of the "nearest multicol ancestor in the same block formatting context" (i.e., the element that establishes the columns being spanned).What happens to the backgrounds, padding, borders, and margins of these elements where the column span interrupts them? Do they appear as though they were a block ancestor of the column-spanning element? (What if they were inline elements?) Does relative positioning on these elements apply to the column-spanning element? Transforms? etc.
This situation is in some ways analogous to the situation that happens when an inline contains a block, which is defined reasonably thoroughly in CSS Level 2, except that this situation is a bit more general since the ancestors being split can be either inlines or blocks, whereas in the block-in-inline situation the split ancestors are only inlines.
I'd note that failing to display the background of an ancestor behind the column-spanning element could violate accessibility expectations related to colors and backgrounds.
What do existing implementations do? (IIRC, Gecko is the last engine to implement
column-span
, which would have made me expect the spec to be in better shape than it appears to be.)/cc @tabatkins @gregwhitworth @neerjapancholi
The text was updated successfully, but these errors were encountered: