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

Closed
dbaron opened this Issue Mar 3, 2017 · 17 comments

Comments

@dbaron
Member

dbaron commented Mar 3, 2017

The definition of column-span doesn't appear to say anything about what happens to the elements that are ancestors of the element with column-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

@frivoal

This comment has been minimized.

Contributor

frivoal commented Mar 4, 2017

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.

@frivoal

This comment has been minimized.

Contributor

frivoal commented Mar 4, 2017

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.

@mstensho

This comment has been minimized.

mstensho commented Mar 6, 2017

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.

@astearns

This comment has been minimized.

Member

astearns commented Mar 8, 2017

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.

@neerjapancholi

This comment has been minimized.

neerjapancholi commented Mar 20, 2017

Tested this on different browsers and posting results with screenshots:
(Let me know if I should add something to this)

Test case: https://jsfiddle.net/5oo2gzLy/8/

Tested on:
Chrome 56.0.2924.87 (64-bit) | Safari 10.0.3 (11602.4.8.0.1) | Edge 38.14393.0.0

Description:

  • ‘Column-span: all’ is applied to break a div in two. This div has border, background, padding and margin set to observe how this is broken across the spanner.
  • ‘Column-span: all’ is nested inside inside an i tag which has a div tag parent. The i tag has border, background, padding and margin set to observe how this is broken across the spanner.

Observations:

  1. Border and background color for div split by column-span is consistent across all three browsers. Also, spanner does not show any indentation or overlap with the background color of the div.
    Screenshot from Chrome but result is same for Edge and Safari -
    screen shot 2017-03-20 at 4 25 06 pm

  2. Border and background for i tag split by column-span is consistent in Chrome and Edge but in Safari you see an extra line at the top of the first column after the column span with a border and no background.
    Screenshot for Chrome but same as Edge:
    screen shot 2017-03-20 at 4 27 12 pm

Screenshot for Safari showing extra line with no background:
screen shot 2017-03-20 at 4 28 17 pm

  1. Spanner nested in i tag does not show any indentation or overlap of background color but it does show the 'Column-span' text italicized in all three browsers. (See screenshots above)
@frivoal

This comment has been minimized.

Contributor

frivoal commented Mar 27, 2017

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:

  • margins/padding/borders/backgrounds/outlines of ancestors of the spanner do not apply to and are not affected by the spanner (other than by the fact that it causes fragmentation)

  • we should clarify/rephrase the spec to say that:

    The property has no effect on elements that are not within the BFC established by the multicol element.

    (resolving #1074 at the same time)

@dbaron

This comment has been minimized.

Member

dbaron commented Apr 5, 2017

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.

@neerjapancholi

This comment has been minimized.

neerjapancholi commented Apr 6, 2017

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;
https://jsfiddle.net/5oo2gzLy/10/

All results are similar (with some minor bugs in Safari and Edge) so posting only one screenshot from Chrome:

chrome -position relative - similar for all

2. Adding transform: rotate(90deg);
https://jsfiddle.net/5oo2gzLy/12/

Chrome:
chrome - transform

Edge:
edge - transform

Safari:
safari - transform

3. Adding filter: grayscale(100%);
https://jsfiddle.net/5oo2gzLy/9/

Chrome:
chrome- grayscale

Edge:
edge - greyscale

Safari:
safari - grayscale

@frivoal frivoal self-assigned this Apr 6, 2017

@dbaron

This comment has been minimized.

Member

dbaron commented May 4, 2017

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 column-span:all element. That is, when you have something like:

      <div style="... maybe something interesting here?...">
          <h2 style="column-span: all">header</h2>
          ... other contents of the div ...
      </div>

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 column-span: all from inlines split by a block? (I'm afraid the answer to both of the last 2 questions may need to be yes.)


It's also worth thinking about the fact that a single inline element might be split both by a block and by a column-span:all element. Those splits propagate up to different levels in the box tree.

@frivoal

This comment has been minimized.

Contributor

frivoal commented May 4, 2017

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.

@frivoal

This comment has been minimized.

Contributor

frivoal commented May 4, 2017

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 column-span:all from

all: [...] Content in the normal flow that appears before the element is automatically balanced across all columns before the element appears.

to

all: [...] A <a>forced break</a> is introduced as if 'break-before: column' had been specified on the <a>spanning element</a>. Content in the normal flow that appears before <a>forced break is automatically balanced across all columns before the element appears, and the rest resumes after the <a>spanner</a>

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.

@frivoal

This comment has been minimized.

Contributor

frivoal commented May 4, 2017

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:

all: The element is taken out of flow, and spans across all columns of the nearest multicol ancestor in the same block formatting context. A placeholder is left in its place, and a <a>forced break</a> is introduced as if 'break-before: column' had been specified on the placeholder. Content in the normal flow that appears before <a>forced break is automatically balanced across all columns before the <a>spanner</a>, and the rest resumes after the <a>spanner</a>

@rachelandrew rachelandrew added this to Unfiled in css-multicol-1 Aug 9, 2017

@rachelandrew rachelandrew moved this from Unfiled to Needs action in css-multicol-1 Aug 9, 2017

@rachelandrew

This comment has been minimized.

Contributor

rachelandrew commented Aug 11, 2017

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?

@css-meeting-bot

This comment has been minimized.

Member

css-meeting-bot commented Nov 7, 2017

The Working Group just discussed column spanning issues, and agreed to the following resolutions:

  • 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 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.
@css-meeting-bot

This comment has been minimized.

Member

css-meeting-bot commented Nov 8, 2017

The Working Group just discussed Background and borders for spanners, and agreed to the following resolutions:

  • 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.
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> ;)

@rachelandrew rachelandrew moved this from Needs discussion to Needs action in css-multicol-1 Nov 8, 2017

rachelandrew added a commit that referenced this issue Apr 8, 2018

@rachelandrew

This comment has been minimized.

Contributor

rachelandrew commented Apr 8, 2018

I've added some text plus an example for these issues to the draft. This is currently example 21, would appreciate a review, and any suggestions or changes. I'll then make sure we have tests for this.

@rachelandrew

This comment has been minimized.

Contributor

rachelandrew commented Apr 8, 2018

I did notice while building some examples on this that where the spanner is the first child of an element with margin, padding and borders implementations then split those across the columns. In the below screenshot the second example is of this case, margin is in column box 1, then the top border, then the padding with a left and right border. This seems logical but I don't think we have any text to this regard.

Example CodePen

screenshot 2018-04-08 15 24 45

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment