[csswg-drafts] [css-pseudo][css-break] ::nth-fragment(An+b) pseudo element (#7517)

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

== [css-pseudo][css-break] ::nth-fragment(An+b) pseudo element ==
https://drafts.csswg.org/css-pseudo-4/
https://www.w3.org/TR/css-break-3/
https://www.w3.org/TR/CSS21/visuren.html#line-box

Could it be possible to target and style the nth-fragment of an element?
I know this might be a pipe dream, but I'm registering an issue here in case it is will be feasible to implement.

```css
span::nth-fragment(2) { ... };
span::nth-fragment(odd) { ... };
span::nth-fragment(-n +2) { ... };
```

### Motivation
We use nth-child and nth-of-type to create variation between sibling elements. Usecases are vast, but vary from changing background colors in tables, to [stagger animations](https://css-tricks.com/different-approaches-for-creating-a-staggered-animation/) and transitions. There is even a [proposal to make sibling-index() and sibling-count() available](https://github.com/w3c/csswg-drafts/issues/4559) to make expressing these variations and staggered animations more flexible.

It would be nice if we could be able to select fragments in a similar way, even though we would have to be very restrictive when it comes to which properties should be available to change and affect inheritance. 

Animations on column or text run fragments could be staggered. Backgrounds and borders on elements with box-decoration-break: clone could be varied. 

At the moment authors have no way of targeting individual fragments, and need to implement the fragmenting layout in js to be able to achieve these goals. There's a [GreenSock plugin](https://greensock.com/SplitText?sub-product=splittext) that does this.

### Considerations

There are more than a few considerations if we were to allow some limited styling of fragments, but I hope they can be mitigated in some way: 

1. Loops
2. box-decoration-break: slice
3. inheritance
4. getComputedStyle
5. transforms
6. inline-box

#### Loops
The first issue could be mitigated by limiting which properties can be changed. Properties like `background*` and `opacity` that doesn't inherit or affect layout should be less problematic.

#### box-decoration-break
I have a feeling that having different background, opacity and border-colors between box fragments when using `box-decoration-break: slice` could be problematic. If so, could allowed properties vary between fragmented boxes with `box-decoration-break: clone` and `box-decoration-break: slice`?

#### inheritance
Setting properties on the `nth-fragment()` would override properties on the breakable box, even if they were higher in the cascade. Thus 'breaking' the cascade. Maybe we can look to [`::first-line`](https://drafts.csswg.org/css-pseudo/#first-line-inheritance) for existing solutions?

#### getComputedStyle
There's an open question on [what getComputedStyle on a fragmentation origin should return](https://github.com/w3c/csswg-drafts/issues/6513) if box fragments can be styled.

#### transforms
[Fragmentation occurs before transforms](https://www.w3.org/TR/css-break-3/#transforms), so each fragment is transformed individually. Transforms that keep the fragment within the fragmentainer should not be problematic, but what should happen when it is transformed outside the fragmentainer? Fragments that are transformed to span multiple pages is specified to be sliced. But it would be great if fragments could be rendered outside the fragmentainer if they are fragmented into a column-box or a line-box.

#### inline-box
There's no syntax for selecting text nodes unless it is wrapped in an inline element. 
```html
<p>Some text <span> some more text </span></p>
```

```CSS
/* this would select fragments of the p, and not fragments of the text run */
p::nth-fragment(odd) {}

/* this would select fragments of the inline span box if it spans multiple line boxes */
span::nth-fragment(odd) {}

/* do we need something like this to select fragments of the whole text run? */
p::text::nth-fragment(odd) {}
```

### Prior art
`::first-line` is a pseudo-element that targets the first line-box of an inline flow. It might be quirky, but experience from specifying and implementing `::first-line` could inform specifying pseudo elements for nth-fragments.

GreenSock has a [plugin](https://greensock.com/SplitText?sub-product=splittext) that splits lines into divs for easy animation.

### Proposal

* Add `::nth-fragment(An+B)` pseudo element syntax to select and style fragments of a box.  Syntax TBB.
* Optionally add `fragment-index()` syntax to make values available for calculation.


```css
/* span would circle between inherited background and lavender background */
span::nth-fragment(odd) {background-color: lavender; }

/* Stagger the second column animation */
section {
  columns: 2;
  &::nth-fragment(2) { animation-delay: 100ms; }
}

/* Stagger in all fragments */
section {
  column-width: 400px;
  &::nth-fragment(n) { animation-delay: calc(fragment-index() * 100ms); }
}
```

This is quite a bit to ask and there are many considerations, but I know there are some really smart people in the CSSWG and among the implementers that might see a way to solve some of the use-cases we would like to achieve.

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


-- 
Sent via github-notify-ml as configured in https://github.com/w3c/github-notify-ml-config

Received on Wednesday, 20 July 2022 10:17:48 UTC