-
Notifications
You must be signed in to change notification settings - Fork 711
[css-display] Make 'flow-root' an independent keyword #1496
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
Comments
Hmmm, okay. So the problem we're dealing with, basically, is that we split the "flow" types into a 2x2 grid of {inline, block}x{flow, flow-root}, but there's a very natural division that groups {block flow, block flow-root, inline flow-root} together separately from {inline flow}, rather than the naive 2/2 splits the syntax creates. This 3/1 split happens to be at least somewhat reflected in the legacy blockification behavior, and possibly in our desired inlinification behavior, too. Your suggestion is to instead use a 2x2x2 {inline-level, block-level}x{auto, block}x{flow-root, ∅} split, giving us 8 options, with several of them effectively identical. I think we can make a slightly simpler 2x3 split that gives us the same necessary distinctions and natural blockification/inlinification behavior, with less duplication: {inline-level, block-level}x{inline, block, block-root}. The mapping we obtain is thus: inline => inline-level inline The two "leftover" combinations, (I'm using This also avoids adding |
The only reason imo to keep |
Okay, more naming thoughts. The reason @fantasai and I went with flow/flow-root is that Block Layout and Inline Layout are pretty intimately intermingled, far more than any other layout modes are. They're only semi-independent, and can be thought of as two fairly distinct modes of a single layout mode: Flow Layout. Under this idea, then, the 3-way split I propose above is more or less "how much do your children mingle with the surroundings?". So here's some non-serious naming suggestions that'll at least let us start usefully talking: { This gives us back |
Useless for table, flex and grid, yes. But I don't think it's useless for ruby. Something needs to be done with ruby when it becomes a formatting context, e.g. it has Just to be sure I understand, you are proposing something like the following, right?
Not bad, I like it :) |
Good point, I'll have to give ruby some more thought.
All correct, yes. And yes, |
This table is more clear. A blockification or inlinification is just a change of column.
With this I don't think we need an About the names, I think Analogously, About ruby, maybe add a new inner type called |
This recategorization is interesting, but I would want to see illustrated examples and how the various transforms render to convince me. I think I understand intuitively what flow-loose vs flow-tight vs flow-root do for inline and block, but it is less clear to me that flow-tight and flow-root are different in other cases like "table", "grid", or "flex". It is my impression we still have indistinguishable combinations with this proposal. Or do these concepts not apply at all in those cases? |
@FremyCompany What Tab proposed is
So they are all mutually exclusive. |
That seems interesting. |
Yeah, they're all display-inline types. Just replacing the current
Yeah, that's valid.
So I suppose the question is - what's the use-case for manually creating a FC-ified ruby? An FC-ified inline is an inline-block, and it's important to be able to trigger this in case you want to put arbitrary stuff inside the inline, like blocks, but still have it flow. But a ruby aggressively protects itself from internal blocks (whether thru recursive inlining or just FC-ifying, we'll determine later), and so isn't capable of the sorts of shenanigans an inline-block can get up to. |
There is this |
That's reasonable. |
I don't like the idea of further splitting the Isn't there any other option? For example, what is the worst implication of allowing And I still believe that a separate value, or maybe even a separate property, to switch on FC-ness of things explicitly would be useful. Maybe it actually has something to do with the scope of [css-containment], and introducing something like |
Yes, it would, because then we could have syntactical equivalences:
Now the spec says
I don't like overlaps between longhand properties, especially when the shorthand is not ordered. But given that both
Yes, this is what I attempted to address in my initial proposal. I don't care if it's via an independent |
Yes, they would be functionally equivalent, but the clear and intuitive naming rule "for any X, I don't like the The |
Remember that my three flow-* names were explicitly called out as being non-serious, and just presented for the sake of having names for the 2x3 values. ^_^ Re: using
Yes, CSS roughly follows the Priority of Constituencies too. But don't be so quick to judge! This sort of thing is easy to dismiss as just spec authors faffing about with more aesthetically pleasing designs, but aesthetics is also an important part of intuitive APIs. If you have to litter an API with corner-cases, it's more difficult to learn and remember for users, and is generally worse. Splitting things out slightly more than the "simplest" case can sometimes lead to much better APIs overall. (It can also lead to worse APIs, as it sometimes is just spec authors faffing about with aesthetics to the detriment of simplicity and usability. One must be ever vigilant!) Often, naming is all it takes to shift something from "theoretically elegant, but overcomplicated" to "elegant and intuitive". I think the |
I'm afraid this might need to stay as |
Yeah, but quite recently. Probably still possible to change if we decided it was worth it. |
Agree! It also is currently defined almost that way, so little change will be needed). By the way, if we re-introduce the
The |
@SelenIT Your proposal is only a rename of Adding a third display type allows to preserve syntactic equivalence, which in my opinion is desirable. Moreover, I think it would be nice if |
@Loirooriol, you are right, I already realized this myself. This can be kind of worked around by changing the blockification rule from "preserve the inner display type, change the outer one to
Again, it's hard to disagree. As I was thinking about that, even a more crazy idea came to me: what if we reconsider the Similarly, instead of one inline outer display type we could have two: ordinary This would automatically solve #1457 by introducing But when I started think on this idea further, I realized that it also would require some non-intuitive rules for blockification (e.g. |
@SelenIT I also considered this possibility, but discarded the idea because inlines and run-ins may also want a FC. You addressed the former with And yes, serialization is non-intuitive and will still have problem #1486, because you are still limited to 4 values: You could add an inner display like But I like Tab's proposal with 6 values. Maybe the flow-abracadabra names were not the best, but they offer more flexibility to the users, because they can choose how the element will be blockified or inlinified. I don't think they are against that Priority of Constituencies principle. May be clearer with the new proposed names:
I think it's reasonably intuitive. There can by syntactic equivalences, and blockifications/inlinifications are simply a change of the outer type. Only some handwaving about blockifying |
I was thinking... if the main concern is that a block-level inline box does not make much sense and thus behaves like a block box, maybe that combination could be syntactically not allowed, at least for now. For example, add a new
That's only 5 basic values. I reused The spec would look like thisSyntax
Outer display roles
If a Inner display models
If a Precomposed inline-level
Transformations
|
I supposed this limitation to be the key part of fixing that issue — there would be no syntactically different forms of inline block with too subtle difference. There is just one layout mechanism inside (the flow layout) and we have 4 options how to inject it into the parent flow (on inline or on block level and as continuation of the parent formatting context or as an "island" of the new one), only one of which corresponds to The Also, all the existing Your last proposal looks interesting, but it seems to me that having two syntactically different things that generate the same box and differ only in one very special case and in a very subtle technical way that doesn't make much sense for a typical CSS author is exactly the key question of #1486, the intent was to avoid this as much as possible. Also, if we selectively prohibit specific values from certain combinations, wouldn't it be simpler to selectively change just the blockification rule for Also, all the proposals that affect only nuances of the |
It seems our points of view are different because you take this for granted and I don't. Unless I'm missing something, this is not in the spec. But yes, making blockified elements "become a formatting context" would allow to preserve syntactic equivalence and flow-root-ness with just 4 flow values. (Well, flow-root-ness would be lost in inheritance). However, I would still consider adding new inner types or an independent
Yes, this could be addressed separately by adding a |
I still believe that there is a significant difference between "usually obviously different, the same in specific conditions" and "indistinguishable in most cases, different in a yet theoretical specific case". And introducing such entities primarily as a workaround for an inconsistency occured because of legacy reasons looks a bit like trying to invent a sledgehammer in order to crack a nut. Currently we have 4 flow layout options (FC-continuing inline box, FC-continuing block box, FC-changing inline box and FC-changing block box) that cover all cases that occur currently in practice, right? We have just a legacy requirement that FC-changing inline box, at least in one of it syntactical forms (which is at the moment the only available option in practice), has to blockify as FC-continuing block box. It seems that neither approach (current Looking for the least complex solution, I came up with the following proposal that from the first glimpse seems to solve both #1457 and the inline-block dilemma:
For inner display values that automatically isolate their contents from the parent flow ( So we would still have 5 options of flow layout:
There would still be two syntactically different ways to get the behavior or the inline-level BFC container, but their distinction would be more obvious (one isolated "from inside" and another "from outside"), and I suppose that |
I don't agree with the analysis, it's not just because of legacy. About your proposal, I'm confused that you are reticent to add more inner display types, which might produce some combinations that behave mostly the same, but instead you propose adding an outer display type, which would have no effect for Note this would not solve the ruby problem entirely. When a |
I would just like to point out that block-level or inline-block-like ruby is not really an important use case (I've never seen anyone requesting it), so whatever we do here shouldn't be contingent on solving that problem. It's fine if it's not possible to specify. |
I was thinking that it's a bit weird that flex items and grid items have a |
The CSS Working Group just discussed
The full IRC log of that discussion<surma> Topic: flow-root syntax<astearns> github: https://github.com//issues/1496 <Florian> 1550 is not listed in the wiki, but also interconnected <astearns> <whiteboarding again> <fantasai> Tab draws a table with columns flow/flow-root, rows block/inline, and values block / BFC / inline-block / inline (clockwise) <fantasai> Tab: block has to inlinify to inline-block, and inline-block has to blockify to block <nainar> https://www.irccloud.com/pastebin/8vyC7bj7/ <nainar> TabAtkins: to make this happen properly - we check if the value is a special value <nainar> TabAtkins: we could break the congruence between legacy values andthe keywrod values so that we define that inline blockifies to block and inline <fantasai> ScribeNick: fantasai <fantasai> TabAtkins: which would mean that inline-block won't behave the same as inline flow-root <fantasai> TabAtkins: even though they're the same thing <astearns> s/andthe keywrod values/and the two-keyword values/ <fantasai> TabAtkins: I have an alternate suggestion <fantasai> TabAtkins: It's still a little confusing, but maybe better <fantasai> TabAtkins: That would avoid breaking existing implementations of flow-root, which have already shipped <fantasai> TabAtkins: First suggestion is that we stick with block and inline <fantasai> TabAtkins: But rather than just two values of flow/flow-root, we have three, calling 1 2 and 3 atm <fantasai> TabAtkins: in increasing order of BFCness <fantasai> TabAtkins: Legacy inline is inline-1 <fantasai> s/inline-1/inline+1/ <fantasai> TabAtkins: legacy block is block+2 <fantasai> TabAtkins: inline-block is inline+2 <fantasai> TabAtkins: 2 is the "keep my children together" value <fantasai> TabAtkins: 3 is the even stronger one, so flow-root is block+3 <nainar> fantasai: <fantasai> TabAtkins: and inline+3 is inline-super-block <fantasai> Florian: What is an inline-super-block? <fantasai> Florian: In which cases do they behave differently? <nainar> fantasai: when does that matter? <fantasai> TabAtkins: If it blockifies it blockifies to flow-root <fantasai> (swap last two) <fantasai> TabAtkins: You contain floats and stuff <fantasai> TabAtkins: So if you have a plain inline block <fantasai> Rossen: You ahve two inline blocks, and they are inside a flex. They both get blockified <fantasai> Rossen: If those have floats inside, those floats don't affect each other <fantasai> Florian, fantasai: Flex items are BFCs <fantasai> Florian, fantasai: When does CSS blockify something and not turn it into a BFC also? <fantasai> TabAtkins: I can't think of any case... <fantasai> Florian: What about the block+1 case? <fantasai> TabAtkins: tiny-block <fantasai> TabAtkins: tiny-block inlinifies to inline <fantasai> Florian: concrete example? <fantasai> TabAtkins: If you have a normal block inside of a ruby container. If you put a tiny-block into a ruby then it turns into a regular inline <fantasai> TabAtkins: falls out of the 2x3 array <fantasai> TabAtkins: I guess then we have two values that fall out and aren't really useful <fantasai> TabAtkins: So in that case, I think we should have a diamond <fantasai> Florian: So how's that different from 2x2? <fantasai> TabAtkins: block and inline-block correspond <fantasai> TabAtkins: I guess flow-root oesn't inlinfiie? Or maybe becomes inline-block? <fantasai> TabAtkins draws a bunch of arrows <fantasai> Florian: I don't know if this is useful..... <fantasai> iank_: Why can't we ? <fantasai> TabAtkins: Because block has to inlinifie to inline-block, and inline-block blockify to block. <fantasai> fremy: getComputedStyle, right <fantasai> Florian: that and display: inherit, which nobody does <fantasai> Florian: Could we say that everything that BFCizes makes you go from block to flow-root ans independnetly from ... <fantasai> Florian: Maybe? <fantasai> TabAtkins: So given that block+1 doesn't have a use case, and neither does inline+3 ... <nainar> fantasai: i think its silly to have a combo that is not useful - cant see how this is better <nainar> s/combo/bunch of combos <fantasai> TabAtkins: I want inlinification and blockification to be simple <fantasai> TabAtkins: 2x2 grid doesn't work, have ot special case things <nainar> fantasai: I think you're overex=hasizng th imp of inlinification of swapping a keyword in an onut <nainar> fantasai: if we take arrows this set of 4 values correspond like that it will be better. <nainar> fantasai: we either have to syntatically disallow or have them do nothing <fantasai> TabAtkins: .... <fantasai> TabAtkins redraws original 2x2 grid <fantasai> TabAtkins draws arrows representing inlinification and blockification <nainar> s/overex=hasizng/overemphasizing <fantasai> TabAtkins: You don't have pairs, a flow-root inlinifies to an inline-block which then blockifies to a block <fantasai> TabAtkins: But that doesn't seem to be a practical concern <fantasai> Florian: ... <fantasai> gregwhitworth: Can you please use words? <fantasai> Florian: If the only dif between block and flow-root is being a BFC <fantasai> Florian: becoming a block ...? <Rossen> [Florian frantically pointing at the whiteboard yelling "this"] <fantasai> TabAtkins: Inline block currently becomes a block when it blockifies <fantasai> TabAtkins: It just happens to be an BFC in all these cases, but its computed value is 'block' <fantasai> TabAtkins: e.g. for flex items, if you specify 'display: inline-block' and ask for its computed display you get 'block' <fantasai> TabAtkins: Generally the case, also for abspos etc. <fantasai> TabAtkins: Because 'flow-root' didn't exist 15 years ago <fantasai> TabAtkins: I don't like it, but I'd be okay with just doing this (points at 2x2) <fantasai> TabAtkins: So it's fine. <fantasai> TabAtkins: OK, so we can analyze the other things <fantasai> TabAtkins: So if we have blockification /inlinification algos just explicitly map these values in the 2x2 grid <fantasai> TabAtkins: Then the next issue is ... <fantasai> TabAtkins: This solves 1246 <fantasai> TabAtkins: where bz points out we get the wrong computed style (get flow-root where breaks legacy) <fantasai> (note to Dael, Rossen's comment goes into the Florian: ... line) <fantasai> Florian: I believe the board is a re-resolution of 1246 <fantasai> TabAtkins: also resolves 1496 <fantasai> TabAtkins: Suggested resolution is that blockfiication of an inline flow-root aka inline-block is defined to go to 'block' <fantasai> TabAtkins: And inlinification of block flow special cases to inline flow-root aka inline-block <nainar> fantasai: 1486 is still open? <fantasai> astearns: So sticking with 1496 <fantasai> RESOLVED: Leave 'display' syntax as-is for #1496 <fantasai> RESOLVED: For 1246, inlinification of 'block flow' goes to inline flow-root aka inline-block, blockfication of inline flow-root & inline-block go to 'block' <fantasai> RESOLVED: For 1486, issue is moot because 1246 resolution was reverted (above) <nainar> fantasai: inline flow-root what is the computed value if we arent blockifying? <nainar> fantasai: the serialization? <fantasai> RESOLVED: 'inline flow-root' serializes in getComputedStyle as 'inline-block' <fantasai> Florian: https://github.com//issues/1550 <fantasai> TabAtkins: This is oriol asking, mechanisms that turn BFCs, why not make them all resolve to display: flow-root instead. And we can't due to web-compat <fantasai> Florian: It's not that there are 2 behavior for flow, there are 4, and flow is way overloaded <fantasai> TabAtkins: 2nd and 3rd are the same thing <fantasai> (of some list that I missed, sorry) <fantasai> TabAtkins: flow creates regular blocks and sometiems BFC <fantasai> TabAtkins: That's just the way it is <fantasai> TabAtkins: oh, I see <fantasai> TabAtkins: Actual suggestion is to change the value at used value time <fantasai> TabAtkins: That doesn't mean anything, because it's post box tree construction <fantasai> TabAtkins: Used values are for turning box tree into fragment tree <fantasai> dbaron: no, used values are just how we describe transformations that happen after inheritance <fantasai> dbaron: i.e. anything that's post-computation <nainar> fantasai: is this editorial? he si saying tha tinstead of describing things as we have it - we shoudl vocab and change flow to flow-root for used value <fantasai> "This change should have no effect in practice." <fantasai> TabAtkins: ... <fantasai> TabAtkins: computed value is eveyrthing before you inherit, and used value is everything after inheritance <fantasai> Florian: No way to distinguish, but you could say that box tree is computed off of used value of 'display' <fantasai> Florian: introducing this concept as a way of explaining what happens <fantasai> fremy: All the old specs we already have will be even more confusing <fantasai> TabAtkins: We already have had to edit every spec <fantasai> TabAtkins: e.g. "height behaves as auto" thing <fantasai> TabAtkins: Not actually every spec anywya <fantasai> TabAtkins: Seems okay <fantasai> TabAtkins: dbaron? <fantasai> astearns: Given item wasn't on agenda, and this is first time apparently anyone understood it... <fantasai> TabAtkins: OK, can discuss later <fantasai> Florian: It was sort of on the agenda, next issue links to this one <fantasai> astearns: OK, let's switch the topic and get minutes posted to the correct issues. |
AKA: we'll make a special-case in "inlinification" and "blockification" to make block <=> inline-block; everything else just sets outer display type to "inline" or "block". inline-block is now back to being identical to "inline flow-root". |
OK, but then please make blockifications trigger becoming a formatting context in order to maintain flowrootness. |
We can't do that due to legacy reasons; "inline-block" has to become "block" when blockified. :( In any case, this was fixed in 2278ea7 |
I have already found multiple people (myself included) confused because
display: block
anddisplay: inline
have the same inner display type,flow
.Making
flow-root
an inner display type overlaps withflow
, and saying thatinline-block
has aflow-root
inner display type is not intuitive and does not work well (#1246, #1486).Additionally, there is the problem of adding layout containment to a ruby element (#1457). I think the obvious fix is making the principal box generated around the ruby container to become a block container (of the specified outer display type) and establish a BFC. But currently no
display
value allows this.So I propose:
Make
flow-root
an independent keyword (similarly tolist-item
) which forces the element to "become a formatting context", i.e an inline box becomes an inline-block, a block container establishes its own BFC, and for ruby this applies to the principal box around the ruby container.Restore the
block
inner display type from 2014 WD, renameflow
toauto
, letauto
behave likeblock
inner display type when block-level. To avoid name clashes, rename the outer display types toinline-level
andblock-level
. That is, undo most part of https://lists.w3.org/Archives/Public/www-style/2015May/0098.htmlSo #1246 is solved as such:
inline-block
is syntactically equivalent toinline-level block
, which behaves likeinline-level flow-root
. The difference is that, when blockified, the formers serializes toblock
(and may no longer establish a BFC) and the latter serializes toflow-root
(and continues establishing a BFC). And the answer to #1486 is that the equivalence betweeninline-block
andinline-level block
is preserved, and theflow-root
-ness is also preserved.Letting an
auto
inner display type compute asblock
if the outer display type isblock-level
after possible blockifications or inlinifications also addresses #1341. You can usedisplay: block-level
(block-level auto
) if you want a block box which inlinifies toinline
(inline-level auto
), or you can usedisplay: block
(block-level block
) if you want a block box which inlinifies toinline-block
(inline-level block
).See my proposed specification and the bikeshed changes.
The text was updated successfully, but these errors were encountered: