Skip to content
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] What is the max-content width of a muticol container with only column-width:<length> #9103

Open
aethanyc opened this issue Jul 21, 2023 · 9 comments

Comments

@aethanyc
Copy link

This is from bug 1844870. See this testcase.

Firefox 115 puts all the content in one column. Google Chrome 117 & Safari 17.0 create many short columns, and the multicol container's width is way larger than the browser window width.

The only relevant spec I found is a note in https://drafts.csswg.org/css-multicol/#pseudo-algorithm

The used width U of the multi-column container can depend on the element’s contents, in which case it also depends on the computed values of the column-count and column-width properties. This specification does not define how U is calculated.

@dholbert
Copy link
Member

The Blink/WebKit behavior seems to be a bug; they seem to be computing the max-content width of the element as if it were not a multi-column container.

Here's a testcase to demonstrate:
https://jsfiddle.net/dholbert/zne65cby/

markup in case the fiddle disappears:

<!DOCTYPE html>
<style>
.container {
  border: 3px solid black;
  width: max-content;
  font: 10px monospace;
}

.multicol {
  column-width: 5em;
  margin-bottom: 5px;
  border-color: orange;
  column-rule: 1px solid red;
}
</style>
<div class="container">
  a b c
</div>
<div class="container multicol">
  a b c
</div>

<div class="container">
  a b c d e f g h i
</div>
<div class="container multicol">
  a b c d e f g h i
</div>

<div class="container">
  a b c d e f g h i j k l m n o p q r
</div>

<div class="container multicol">
  a b c d e f g h i j k l m n o p q r
</div>

<div class="container">
  a b c d e f g h i j k l m n o p q r s t u v w x y z
</div>
<div class="container multicol">
  a b c d e f g h i j k l m n o p q r s t u v w x y z
</div>
  • Firefox consistently sizes the orange-bordered multicol elements to 5em wide (the width of a single column).
  • Chrome/Safari consistently size the orange-bordered multicol elements as being the same width as their black-bordered non-multicol sibling. In other words, they're resolving width:max-content as if the element were not a multicol.

@dholbert
Copy link
Member

Screenshot of my above-linked jsfiddle in Firefox:
image
vs. Chrome:
image
vs. Epiphany/gnome-web (using WebKit):
image

@dholbert
Copy link
Member

dholbert commented Jul 24, 2023

Here's another testcase to get at what browsers are doing here: https://jsfiddle.net/dholbert/5ak3xdnh/

This one has two multicol elements, which each have a single child. In the first multicol, the child has the alphabet laid out on one line (characters separated by spaces). In the second, the characters are separated by br elements.

Chrome/WebKit render the first multicol element as having several columns (since they're using what-I-think-is-a-bogus measurement for the max-content width, calculated as if the element were a regular block); and they render the second multicol as having one column (correctly). Firefox renders both multicols as having one column (correctly, I think).

Comparing the two multicol elements: the child element obviously has a larger max-content width in the first one, since it's got a long single line of content. But that doesn't mean the multicol element should also have a larger max-content width. The multicol element's content-width should be essentially determined by the column-width and number-of-columns. So if either of the multicols in this fiddle were going to be extra-wide, it should be the second one (where the child is taller and hence more capable of generating columns beyond the first), -- i.e. the opposite of the Chromium/WebKit behavior. But really there's nothing forcing any fragmentation breaks here, so both of these multicol elements should have a single column, with a max-content width being the width of that column.

@frivoal frivoal added the css-multicol-1 Current Work label Oct 2, 2023
@rachelandrew
Copy link
Contributor

Just looking at this, there used to be a definition of the size of the container in Box Sizing (when it was still Intrinsic and Extrinsic Sizing) but it was removed and I don't think it has made it back into the level 4 spec. I think that's probably where this should be defined.

@mstensho
Copy link

This is a dup of #1742 isn't it?

@rachelandrew
Copy link
Contributor

Been poking around some more at this, just to clarify:

With a:

  • column-width: <length>
  • column-count: auto
  • inline-size: max-content on the multicol container

Firefox makes the max-content size the width of one column, and puts all content into that one column.

Chrome and WebKit make the max-content size the size it would be if we do inline-size: max-content in block layout. Then put the content into as many columns in as will fit.

I think Firefox is doing what the removed text says though not sure if that's what people would expect of a max-content multicol container.

Adding to the agenda to ask the following questions:

  1. Should this be defined in Sizing or in Multicol (level 2 at this point)? The current multicol L1 spec states that another spec is expected to define it.
  2. What behavior do we want when a multicol container has an inline-size of max-content?

Browsers do seem to be interoperable with inline-size: max-content and a column-count: <integer>. Example of both here: https://codepen.io/rachelandrew/pen/dyadbaL

@dholbert
Copy link
Member

@rachelandrew yup, your description of the behaviors matches my observations in my previous comment (though you stated it more clearly than I -- thanks!)

RE what behavior we'd like here: the Firefox behavior is at least simple and understandable. I'm happy to consider even-more-reasonable behaviors if they're not too complex/expensive, but I think the Chromium/WebKit behavior for the column-count:auto scenario ends up using a width that's pretty arbitrary and doesn't make much sense. The arbitrariness is particularly noticeable when the content is all on one line, as demonstrated by my above-linked jsfiddle, and in this abbreviated version of Rachel's codepen. Screenshot of that pen in Chrome -- notice all the awkward blank space on the right, and the text wrapping at ~2.5 lines per column:
image
Chrome is sizing the container to the max-content width of the content-as-if-it-were-a-regular-block (i.e. the length of that line of text); and as you can see in the screenshot, that's not at all related to how wide the content actually ends up being, when laid out in a multicol setting with specified-width columns. So it's not really a meaningful/useful max-content measurement for this container.

@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed [css-multicol] What is the max-content width of a muticol container with only column-width:<length>, and agreed to the following:

  • RESOLVED: Define the behavior we want with forced breaks (column-width * (forced-break-count + 1)), with the forced-break situation at risk, in multicol L2
The full IRC log of that discussion <emilio> rachelandrew: so there's this interop issue if you have a fixed column-width, column-count: auto, and max-content on the container
<emilio> ... FF uses one column with everything else
<emilio> ... WebKit / Blink uses the max-content size of the inner thing
<florian> q+
<emilio> ... this used to get spec'd to say what FF did, but got removed
<emilio> ... none of the behaviors seems particularly useful
<emilio> ... Q: should this be part of multicol or sizing?
<emilio> ... Also: what behavior do we want?
<emilio> ... the ff behavior is probably more useful
<emilio> ... I put a codepen in the issue with an example of a huge
<emilio> florian: I suspect ff behavior is better
<astearns> ack florian
<emilio> ... yeah it's a single column but it's a single size
<emilio> ... chrome will size it as it was a block but due to gaps and such then it would create columns
<emilio> ... ff behavior is simple and non-dangerous
<emilio> rachelandrew: my guess is that this were to happen this would be a mistake
<astearns> ack dbaron
<emilio> ... so really I think we should just get interop on it
<emilio> dbaron: I can think of two other somewhat-reasonable possibilities for what this might mean
<emilio> ... one is to count all the column-breaks and you have that number of columns
<emilio> ... the other find the longest required height between column breaks, and compute the number of breaks that you'd have if you were breaking at that height
<emilio> astearns: there's nothing about height
<emilio> iank_: you could be height-constrained
<emilio> dbaron: in that sense multicol is conceptually like a writing-mode switch
<emilio> ... in that you can be using a height as input and a width as output rather than the other way around
<emilio> ... not sure if people actually want these things
<emilio> ... if you want a multicol that could be as short as possible then this could be what you want?
<emilio> ... not sure if worth the complexity
<emilio> rachelandrew: I couldn't come up with any use case that justifies making anything more complicated
<emilio> ... not sure that that value would infer what you're suggesting this could do
<astearns> ack fantasai
<Zakim> fantasai, you wanted to bring up the fixed height question
<emilio> fantasai: so a long time ago tab and I tried to map what are the intrinsic sizes for multicol
<emilio> ... we dropped that because nobody was interested in it
<emilio> ... the idea was that it should go in multicol, but it ended up in sizing
<emilio> ... the questions you need to ask is:
<emilio> ... what is the goal of max-content? Lay out assuming you have infinite spaceew
<emilio> s/spaceew/space
<emilio> ... then you choose the size that is doesn't use more space than you can usefully use
<emilio> ... so you wouldn't layout a max-content size of 100x the column width if you have 5x the column-width
<emilio> ... if you have an unrestricted block size then you are not going to break and you have only 1 column
<emilio> ... if you have a forced column break you could have a bigger max-content
<emilio> ... so you could use (n+1)*forced-column-break-count
<emilio> ... then you also need to know what to do if you have a constrained height
<emilio> ... but then you need to do layout and it gets complex / cyclic with spanners / etc.
<emilio> ... we defined something that was getting the right answer in most cases
<emilio> ... so that's a bit of the history and thought process
<emilio> ... so for unconstrained height I think we could do (n + 1)*forced-column-breaks
<emilio> ... the constrained case is more complicated
<dbaron> (N-forced-column-breaks + 1) * width, I think
<emilio> rachelandrew: that's reasonable but not sure what ff does with force column breaks
<emilio> err, yes
<emilio> dholbert: I don't think we look at forced breaks
<emilio> rachelandrew: so you think it should go to multicol instead of sizing?
<emilio> fantasai: yeah, probably
<dholbert> https://bugzilla.mozilla.org/show_bug.cgi?id=1840944 (open) is filed on �break-before:column� in Firefox
<dbaron> dbaron: I had forgotten we'd changed multicol so auto heights didn't lead to non-forced column breaks.
<emilio> iank_: we'd need to do layout to know how many forced column breaks you need
<emilio> ... because some forced column breaks might collapse into each other
<emilio> q+
<emilio> astearns: would you be fine with that?
<astearns> ack emilio
<emilio> iank_: I think so, need to check with mstensho but I think it'd be fine to run layout inside the max-content computation
<TabAtkins> emilio: i have a slight pref to avoid doing layout during intrinsic sizing
<TabAtkins> emilio: I think it's just - it's an easy way to create perf bottlenecks
<fantasai> [archived slides for the scoped transitions discussion: https://lists.w3.org/Archives/Public/www-archive/2024Feb/att-0000/scoped-transitions.pdf ]
<TabAtkins> iank_: welcome to my life
<TabAtkins> iank_: was this issue from a webdev?
<TabAtkins> emilio: from xxx
<TabAtkins> iank_: we could resolve on the firefox model for now and fix it later if we actually need it
<TabAtkins> emilio: yeah i'd prefer that. doing layout for intrinsic size creates funky problems
<TabAtkins> TabAtkins: don't we already have that for column flexboxes?
<TabAtkins> iank_: Yup. Grid too. But we're the only one that's shipped the flexbox behavior.
<emilio> s/xxx/Ting-Yu, who works with us
<TabAtkins> astearns: so two options. (1) spec the firefox behavior, whcih isn't useful but is less weird, or (2) do the thing with forced breaks, which is less simple but more useful
<emilio> astearns: so two options, spec FF behavior, or do the actual thing with forced breaks that is useful that nobody asked for
<emilio> fantasai: I propose to spec the forced-break behavior and mark the behavior as at-risk
<emilio> florian: the behavior with force breaks is somewhat complicated
<fantasai> s/at-risk/at-risk for handling forced-breaks/
<emilio> florian: so the complication for unconstrained size is counting the forced breaks, right
<emilio> fantasai: the constrained case is harder but this should be relatively straight-forward
<emilio> astearns: so resolve on accommodating force breaks, put it at risk in L2?
<florian> s/counting the forced breaks/figuring out which forced breaks coincide
<emilio> RESOLVED: Define the behavior we want with forced breaks (column-width * (forced-break-count + 1)), with the forced-break situation at risk, in multicol L2

@alisonmaher
Copy link
Collaborator

I was thinking about this one some more, and I think the point from @bfgeek in the minutes is correct in that we would need to run layout to get the number of forced breaks needed.

One example where this would be necessary is with relation to flexbox fragmentation. According to the spec, "In a row flex container, the break-before and break-after values on flex items are propagated to the flex line."

The main problem this poses is that there may be more than one forced break in the same line, so naively counting the number of forced breaks would be incorrect, since two forced breaks in the same line will only produce one true forced break before or after the current flex line.

Unless we run layout, we will not know which items are placed in which lines, and thus, where the forced breaks will apply to (and which will be ignored due to an earlier forced break in the same line). Flex lines are also not a part of the DOM, so we do some "magic" at layout time to apply these various breaks according to where the items ended up, meaning that knowing the exact number of columns created due to forced breaks in the case of flex fragmentation is impossible before layout.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Feb 2024 Agenda
Monday afternoon
Development

No branches or pull requests

8 participants