[csswg-drafts] [css-ruby] Box model / layout model for nested ruby containers (block axis) (#4980)

frivoal has just created a new issue for https://github.com/w3c/csswg-drafts:

== [css-ruby] Box model / layout model for nested ruby containers (block axis) ==
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:
```html
<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](https://drafts.csswg.org/css-ruby-1/#nested-pairing), 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](https://user-images.githubusercontent.com/113268/79735659-92f01600-8333-11ea-9db5-cc7354bd5e1d.png)

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

According to the [Box fixup steps](https://drafts.csswg.org/css-ruby-1/#box-fixup), 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):

```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](https://drafts.csswg.org/css-ruby-1/#ruby-layout) 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.

Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/4980 using your GitHub account

Received on Tuesday, 21 April 2020 04:13:40 UTC