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-ruby] Box model / layout model for nested ruby containers (block axis) #4980

Closed
frivoal opened this issue Apr 21, 2020 · 4 comments
Closed
Assignees
Labels
Closed Accepted by CSSWG Resolution Commenter Satisfied Commenter has indicated satisfaction with the resolution / edits. css-ruby-1 Current Work Needs Testcase (WPT)

Comments

@frivoal
Copy link
Collaborator

frivoal commented Apr 21, 2020

Nested ruby gets us into the more intricate cases of ruby layout, so I want to figure out what it's box model and layout model is. It's not just a matter phrasing it right, because depending on what boxes are there, how they affect each other, we'll get different layouts when changing properties that apply to them.

Let look at an example:

<ruby>
  <rb>A</rb>
  <ruby>
    <rb>B</rb>
    <rb>C</rb>
    <rt>b</rt>
    <rt>c</rt>
  </ruby>
  <rt>a</rt>
  <rt>b+c</rt>
</ruby>	

The section about nesting ruby, says how pairing and level assignment in the case of nested ruby elements work, and this gives us something that looks like this:

Screenshot 2020-04-20 18 18 07

(Leaving aside the precise size of things, that is what Firefox does).

According to the Box fixup steps, the inner ruby gets wrapped up in an anonymous ruby base, and anonymous base/annotation containers get created too. So the box tree looks like that (with a-* indicating the anonymous boxes created by the box fixup, and rbc indicating ruby base containers, even thought there's no such element in HTML):

<ruby>
  <a-rbc>
    <rb>A</rb>
    <a-rb>
      <ruby>
        <a-rbc>
          <rb>B</rb>
          <rb>C</rb>
        </a-rbc>
        <a-rtc>
          <rt>b</rt>
          <rt>c</rt>
        </a-rtc>
      </ruby>
    </a-rb>
  </a-rbc>
  <a-rtc>
    <rt>a</rt>
    <rt>b+c</rt>
  </a-rtc>
</ruby>               

So both it terms of expected layout and of box tree, I think this is clear. But the geometry of these boxes is much less so, as the current layout section isn't clear which boxes are affected in what way when there is nesting.

In this issue, I'd like to focus on the block axis (sizing in the inline axis is reasonably intricate, but not particularly complicated with regards to nesting).

Having considered a few possibilities, here's how I think this ought to work:

  • The height of the content area of <rb> and <rt>, and <ruby> boxes is sized the same way the height of inline boxes is: they have a fixed height that depends on font metrics, but does not depend on the dimensions of any descendant box.
  • the content area of ruby base containers are set to the smallest rectangle that fits around all their descendants (not just children) ruby bases and ruby annotations, considering their margin boxes (as currently specified). Same thing for ruby annotation containers.

Mixing that with the rest of the spec, this allows us to answer questions like:

  • What happens if you add padding-top to the inner bases (B or C in the example):
    => both levels of annotations are shifted up by that amount, because:

    • The inner ruby's base container grows to accommodate these padded bases, which pushes up the first level of annotations (b and c), since they're stacked on top of it.
    • the inner ruby container does not grow taller
    • the base that wraps around the inner ruby container does not grow taller
    • the outer ruby's base container not only contains the bases that are its direct children, but all its descendant bases and annotations, recursively, and so it will go from the bottom of "A", "B", and "C" to the top of "b" and "c".
    • The outer ruby's annotation container is stacked on top of that
  • What happens if you add padding-top to the outer bases (A in the example):
    => The inner level of annotation doesn't move, and the outer level of annotations is shifted up when the size of the padding exceeds the size of the inner level annotations, because:

    • the outer ruby's base container not only contains the bases that are its direct children, but all its descendant bases and annotations, recursively, and so it will go from the bottom of "A", "B", and "C" to the top of "b" and "c", unless A has so much top padding that it would go higher than the top of "b" and "c", in which case the the outer ruby's base container will go from the bottom of "A", "B", and "C" to the top of "A"'s padding.
    • The outer ruby's annotation container is stacked on top of that

Since the size and position of of all these various boxes are then well defined, we also have no issue knowing where to paint their backgrounds if they have one.

I can think of some alternative models that would result in the intended layout, but they'd either need some additional anonymous boxes, or some degree of re-parenting annotations of inner levels into the outer ruby container (or both), and this extra complication doesn't look like it would do any good.

@frivoal frivoal added the css-ruby-1 Current Work label Apr 21, 2020
@frivoal frivoal self-assigned this Apr 21, 2020
@upsuper
Copy link
Member

upsuper commented Apr 30, 2020

I'd like to mention that this is not what Firefox currently does.

Firefox's model is: when positioning ruby annotation containers of segment, it starts from the outside of all ruby annotation containers of inline ruby containers nested inside the ruby base container of that segment.

Implementation-wise, it's done the way that after reflowing a ruby container, the total leadings created outside the ruby base container would be recorded and reported to the closest inline ruby base container ancestor, and when positioining ruby annotation containers, such leadings would be taken into account.

Having written that, I think the implementation doesn't actually match the model I described above in the way that if the inner base has different font size than the outer base, it would be wrong... but playing with Firefox's implementation I don't see such bug... I'm now confused...

@upsuper
Copy link
Member

upsuper commented Apr 30, 2020

If we ignore the size of base container got from some JS API, and if we make ruby base container itself not render anything, then your model and my model probably don't differ a lot I guess.

@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed Box model / layout model for nested ruby containers (block axis), and agreed to the following:

  • RESOLVED: accept the proposal in the issue, with the caveat that it should apply only to in-flow content
The full IRC log of that discussion <astearns> topic: Box model / layout model for nested ruby containers (block axis)
<astearns> github: https://github.com//issues/4980
<emilio> florian: I think this one is a little bit more involved
<emilio> ... but the previous ones have cleared the way so that we have less moving pieces
<emilio> ... you can have a ruby inside the base or the annotation
<emilio> ... how these behave is interesting
<emilio> ... let's say we have a ruby inside of a base
<emilio> ... currently the spec defines this
<emilio> ... but it's not clear if the wrapping around descendants happens for only direct descendants or for all descendants
<emilio> ... I think the answer that makes more sense is that the base container is sized to wrap tightly around all the descendants
<emilio> ... and same for the annotation containers
<emilio> ... would probably be easier with a whiteboard
<emilio> fantasai: I think this model makes sense, if we add _in flow_ descendants
<emilio> ... I think it doesn't require the layout model to dig through nested levels other than via the sizes of the boxes, which makes this simpler
<emilio> xidorn: I think FF is currently doing something magically
<emilio> ... not sure how it'd differ in practice
<emilio> florian: I couldn't understand what magic FF is doing, but the effects of it seem less useful
<emilio> ... when you have nesting there's more spacing than there would be from this model
<emilio> ... and I don't know where it is coming from
<emilio> xidorn: [missed]
<emilio> koji: I agree that if you look at this case the proposed model looks good
<emilio> ... I have my preference to not define this because this is not demanded by users and this is a special case / divergence from inlines
<emilio> florian: that part of ruby is already different
<emilio> ... bases and annotations can take border / margin / padding
<emilio> koji: it seems this model requires looking at the ruby base of the bc
<emilio> florian: it's not the base which is sized different from inlines, it's the container which would be sized magically
<emilio> koji: which base?
<emilio> florian: let's have two levels, the outer rbc and the outer rb inside which there's a ruby ...
<emilio> ... all the ruby bases and containers are sized like inlines
<emilio> ... but the outer ruby base containers gets sized to wrap all the descendant bases and annotations
<emilio> fantasai: yeah the base container sizing needs to be special
<emilio> ... otherwise we can't account for "one of the bases has grown the font-size"
<emilio> ... it needs to grow to fit the bases that are inside them
<emilio> ... I'd go further to make this more consistent, we may want to consider that the base container is sized to fit their bases and any other base containers
<emilio> ... or maybe that it fits all of the margins of all of the inlines inside it
<emilio> ... in which case the definition would just work
<emilio> xidorn: it would not
<emilio> ... because annotations are not inlines
<emilio> fantasai: oh, that's right
<emilio> koji: ok
<xidorn> s/annotations are not inlines/annotation containers are not inlines/
<emilio> koji: can we mark it at risk?
<emilio> florian: not sure it's the right term for this, but we'll actually come back to this
<emilio> ... after this we have enough info to write the block layout
<emilio> florian: at risk means we can remove it when switching from cr to pr
<xidorn> florian: could you send me an example that you see Firefox's behavior unhelpful? from my testing there doesn't seem to be difference on annotations.
<emilio> fantasai: I think defining nested ruby so that it actually works is the right thing to do for the spec
<emilio> florian: and the spec was already hinting at this working, it just didn't say how
<fantasai> nested ruby testcase - works in Chrome and Firefox http://software.hixie.ch/utilities/js/live-dom-viewer/?%3C!DOCTYPE%20html%3E%0A%3Cruby%3E%3Cruby%3EABC%3Crt%3Eabc%3C%2Frt%3E%3C%2Fruby%3E%3Crt%3Exyz%3C%2Fruby%3E
<fantasai> It should continue to work, fundamentally. It's ok if the exact spacing is a bit off, but not ok if the two annotations paint on top of each other.
<emilio> florian: xidorn: the screenshots in the issue are just FF with a bit of photoshop
<emilio> xidorn: what's going on it's the whitespace taking height
<emilio> ... you can remove it and you see what you want
<emilio> fantasai: so currently nested ruby works in both Chrome and FF
<emilio> ... so we need to make sure that it keeps working correctly
<emilio> myles: nested ruby is actually pretty common in books
<emilio> astearns: agree, that's why I think we should define it in the spec
<emilio> RESOLVED: accept the proposal in the issue, with the caveat that it should apply only to in-flow content

@upsuper
Copy link
Member

upsuper commented May 6, 2020

Thinking about this again, I found that it would be interesting if the nested ruby is inside a vertical-aligned span inside another ruby base. It would come back to the vertical-align issue we discussed on day 2 but with an even trickier situation.

@frivoal frivoal added Needs Testcase (WPT) Commenter Satisfied Commenter has indicated satisfaction with the resolution / edits. and removed Needs Edits labels Feb 1, 2021
@frivoal frivoal closed this as completed Feb 1, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Closed Accepted by CSSWG Resolution Commenter Satisfied Commenter has indicated satisfaction with the resolution / edits. css-ruby-1 Current Work Needs Testcase (WPT)
Projects
None yet
Development

No branches or pull requests

4 participants