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-display][css-ruby] Does inlinification really need recursion? #1341

Closed
Loirooriol opened this issue May 9, 2017 · 11 comments
Closed

[css-display][css-ruby] Does inlinification really need recursion? #1341

Loirooriol opened this issue May 9, 2017 · 11 comments

Comments

@Loirooriol
Copy link
Contributor

CSS Display defines inlinification as such:

inlinification [...] sets the box’s outer display type, if it is not none or contents, to [...] inline [...]

If a box with a flow inner display type is inlinified, it recursively inlinifies all of its in-flow children, so that no block-level descendants break up the inline formatting context in which it participates.

I think it makes more sense to transform the flow inner display type into flow-root. That is, transform block to inline-block. Then the box will be an atomic inline, and thus block-level descendants won't break up the inline formatting context. Recursive inlinification is not needed.

This seems what Firefox does for ruby. Chrome and Edge don't inlinify at all. https://jsfiddle.net/d1o5k7Ly/1/

It's worth noting that CSS Ruby says "directly contained"

Inlinize block-level boxes: Any in-flow block-level boxes directly contained by a ruby container, ruby base container, ruby annotation container, ruby base box, or ruby annotation box are forced to be inline-level boxes, and their display value computed accordingly.

By the way, are inlinization and inlinification synonyms?

@tabatkins
Copy link
Member

You're correct the making them flow-roots prevents the need for recursion, but that ignores that now you have a flow-root. That's not a meaningless change! In particular, it means they won't line-break anymore.

It's worth noting that CSS Ruby says "directly contained"

Which is unfortunate, and should be fixed. Ruby's last update in the relevant area was long before we defined inlinification (but fantasai and I definitely defined it for the purpose of Ruby).

@tabatkins tabatkins added css-display-3 Current Work css-ruby-1 Current Work labels May 9, 2017
@Loirooriol
Copy link
Contributor Author

Not a meaningless change, but converting whole subtrees of blocks to inlines seems also very drastic. Well, I don't really care about recursion, but then please update the ruby spec, otherwise it's confusing.

@tabatkins
Copy link
Member

Yup. Pinging @fantasai for verification that Ruby needs updating.

@upsuper
Copy link
Member

upsuper commented May 13, 2017

Ruby boxes are supposed to be inline box, and they should share all the characteristic of inline box like kerning.

Recursion isn't really a big issue, because in general content in ruby is expected to be small and shallow, and actually block-in-ruby should be considered a wrong use, which means handling it should not affect normal usecases, and it should be as easy as possible for impl.

@fantasai
Copy link
Collaborator

fantasai commented May 16, 2017

So, there are two definitions being considered here:

  • Display's definition that blocks are recursively turned into inline boxes
  • Ruby's definition that blocks are turned into inline-blocks.

I think either definition is reasonable. Agree with Tab that we should be consistent across ruby and run-ins, but I don't have a compelling reason to prefer one or the other.

@tabatkins
Copy link
Member

tabatkins commented May 16, 2017

So the core point of inlinification is to ensure that nothing can break the inline context it's working in. "block flow-root" elements become "inline flow-root" ("inline-block"), which is fine - they're atomic inlines. But "block flow" naively becomes "inline flow", which still allows descendant blocks to bubble up a break.

The current text solves this by recursing, so that a "block flow" becomes "inline flow", then its children inlinify as well, ensuring there's no visible block descendants.

Instead turning "block flow" into "inline flow-root" also solves this, by hiding any descendant blocks.

Either solution solves the problem. Are there any good use-cases or impl considerations suggesting that we go for one vs the other?

@tabatkins
Copy link
Member

@fantasai points out a strong reason not to use "inline flow-root" - it means that any inline elements inside a ruby will become inline-blocks, unnecessarily preventing linebreaking from occurring on the children, and disrupting inline layout in general (breaks shaping and justification across boundaries, etc).

@fantasai
Copy link
Collaborator

Okay, so afaict both the Ruby and Display definitions are pretty broken atm. :) Ruby fails to recurse into inlines, which it needs to do in order to suppress line breaks. The Display module turns 'display: block' into 'display: inline' and then recurses into it, which is also problematic because blocks should stay together as a unit.

@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed inlinification, and agreed to the following resolutions:

  • RESOLVED: inline-block because they're awesomeish
The full IRC log of that discussion <ChrisL> topic: inlinification
<tantek> github topic: https://github.com//issues/1341
<tantek> TabAtkins: our current ... does ... but not ...
<tantek> TabAtkins: in order to keep certain inline layout modes in particular ruby from being broken up by blocks sohwing up in
<tantek> TabAtkins: we use inlinification
<tantek> TabAtkins: but as currently defined in the display module it might be too aggressive
<tantek> TabAtkins: in particular it turns current blocks bfcs into inlines
<tantek> TabAtkins: which preserves the inliniciation but almost certainly messes up your intended layout
<tantek> TabAtkins: Blocks become inlines.
<TabAtkins> s/current blocks bfcs/plain blocks (not bfcs)/
<tantek> TabAtkins: the other way we could do it
<tantek> TabAtkins: make all types of blocks, flow root or flow, turned inline blocks
<tantek> TabAtkins: this would preserve display a bit more closely to what intended
<tantek> TabAtkins: inline block
<tantek> TabAtkins: but is a little more complicated in the spec
<tantek> TabAtkins: otoh we probably have to do the opposite for blockifications, turning inline blocks into block flow, not block root
<tantek> TabAtkins: if anyone knows of any impl difficulty one way or another, let us know
<Rossen> <div> text <span> more text <div>am I inline?</div> end text </span></div>
<tantek> TabAtkins: otherwise we may go the latter way, inline blocks turning into plain blocks
<tantek> Rossen: I have a question and just pasted an example
<tantek> Rossen: (describes example)
<tantek> TabAtkins: inlinification is not triggered by that
<tantek> TabAtkins: but if instead of a span you had a ruby
<dbaron> Isn't part of the problem here that there's not inline-block variant that *isn't* flow-root -- and that such a thing doesn't necessarily make sense?
<tantek> TabAtkins: it would no longer be a block
<tantek> Rossen: what does inlinification apply to
<tantek> TabAtkins: ruby bases and text, and I think there is one more context, run-ins?
<dbaron> But inlinification of block -> inline-block does seem to make sense, as long as there aren't compatibility problems.
<dbaron> What do implementations do?
<tantek> Rossen: in that case if it is only tied to those 2-3, then it shouldn't be much of a problem
<fantasai> dbaron, I think the complexity here is that 'flow' for blocks can mean flow-root depending on various external things, and historically these cases have a display type of 'block' not 'flow-root'.
<tantek> TabAtkins: dbaron, they do inconsistent things, bc run-in not impl yet, ruby spec describes different thing that is broken in its own way, because it doesn't stop blocks from breaking things, so it is doing something, but inconsistent with many things, unclear what impls actually do
<tantek> fantasai: one thing to keep in mind for ruby, the only impl that even remotely follow the spec is Firefox, the other two impls are tag-based hacks in layout that hook into inline layout code
<tantek> fantasai: as far as we are concerned there is only one impl of Ruby spec
<fantasai> s/inline/inline-layout/
<fantasai> s/Ruby/CSS Ruby/
<tantek> Rossen: how many impls follow HTML ruby spec?
<tantek> Rossen: ruby spec as it is not ready for imply in our opinion that is why we are not impl it
<tantek> Rossen: re: ruby interop, HTML ruby interop is good
<tantek> Rossen: then there is the spec in the works which it is hard to argue what is interop and what is not
<tantek> Rossen: question, do we know what is from the author / content point of view the expected behavior?
<tantek> Rossen: do we not break anything in the ruby context e.g. blocks? or do we need to blockify?
<tantek> fantasai: the general case is that ruby is not expected to contain block level content, generally just text, not enough text to wrap, though there are some pathological cases where the text does wrap
<tantek> fantasai: we are trying to stop the bleeding
<tantek> fantasai: we don't want ot have to deal with how do you break ruby annotations across lines
<tantek> fantasai: so we are inlinifying
<tantek> fantasai: similar for run-ins
<tantek> fantasai: e.g. if you have a headline and want to run into the next paragraph
<tantek> fantasai: if you stuck a block in that headline, then it's not going to run-in properly
<tantek> fantasai: we could say if you have a block inside, then you could say it does not run-in
<tantek> fantasai: but then you have to inspect all the way down
<jensimmons> +1
<tantek> fantasai: we just want to check the element its properties and parent(s)
<tantek> fantasai: ... inline-block ...
<tantek> fantasai: or we ... to turn into inlines
<TabAtkins> (A simple test-case: http://software.hixie.ch/utilities/js/live-dom-viewer/?saved=5218. Chrome's rendering is *incoherent* here, so our behavior can't be depended on.)
<tantek> fantasai: ... everything is contain in a bfc that is now inline
<tantek> Rossen: I agree with that logic
<tantek> Rossen: is this an error case?
<jensimmons> what fantasai just said sounds right to me. Turn it into an inline block
<tantek> Rossen: in which case I expect exceptions or something more dramatic
<tantek> Rossen: so as an author I can see something wrong and go fix it
<tantek> Rossen: rather than us trying to make it sorta work
<jensimmons> as an author I would expect that is the ‘right’ behavoir
<tantek> Rossen: if this is an error, let's make this very obv
<tantek> Rossen: otherwise if we patch it up so it sorta looks ok, then it's not going to be as good
<ChrisL> I agree with Rossen on this
<tantek> fantasai: whatever we come up with is going to look weird
<tantek> dbaron: to some extent, inline is a more obv error than inline-block for something that was originally a block
<tantek> fantasai: but is also more work
<tantek> fantasai: and I don't see that that is necessary
<tantek> ??? : what about display none?
<tantek> fantasai: absolutely not
<fantasai> s/???/fremy/
<tantek> fantasai: this is the web platform and we do not make things disappear as an error case [except for XML draconian heads :P ]
<gsnedders> s/???/francois/
<tantek> Rossen: inlineness down recursively...
<tantek> Rossen: I would be in favor of either inline-block or block
<tantek> jensimmons: I hear about things breaking more badly, but in a practical reality, most authors struggle to understand inline-block vs block vs inline does
<tantek> jensimmons: I think make it inline-block make it seem less broken
<tantek> jensimmons: feels like make the outer inline while everything stays block is how it supposed to work?
<tantek> jensimmons: authors are already struggling. making it more broken for them is not going to help
<tantek> fantasai: it is not really an error case
<tantek> fantasai: but we need to do something with it
<tantek> TabAtkins: while doing inline-block is a little more complicated from the spec perspective, it is fairly insignificant, it's fairly straightforward, I'm happy to go with what makes more sense
<tantek> astearns: I am hearing people are ok with either inline or inline-block
<tantek> astearns: but some pref for inline-block
<tantek> astearns: so we should resolve inline-block and see how it goes
<Rossen> inline-block ftw because they are awesome(ish)
<tantek> astearns: any objection to inline-block in this instance?
<tantek> RESOLVED: inline-block because they're awesomeish
<tantek> astearns: next thing
<tantek> TabAtkins: exact opposite case
<tantek> TabAtkins: when you blockify an inline-block what happens

@fantasai
Copy link
Collaborator

fantasai commented Jul 5, 2017

Cross-linked Ruby to the css-display 'inlinification' definition.

Also, to answer the original question, yes, it needs recursion, because inline boxes should remain untouched by this process.

@fantasai
Copy link
Collaborator

fantasai commented Mar 20, 2018

Since inlinification doesn't affect layout-internal display types (expecting such boxes to be wrapped in an appropriate anonymous inline-level wrapper by the relevant box-fixup rules), I also added ec80a76 to address misparented internal table boxes inside ruby. (We were assuming they'd be considered inline-level due to fixup, but weren't really clear on that since if box fixup hasn't run yet, they aren't.)

CSS Tables L3 already recognizes ruby in determining anonymous table box types.

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

No branches or pull requests

5 participants