Re: [csswg-drafts] [css-scroll-animations] Rethinking declarative syntax for scroll-linked animations (#6674)

Thanks for your feedback @mirisuzanne. It's great to see how you approach this from CSS up, whereas the spec as it stands right now was clearly written from a JS-first stance, and then translated to CSS.

If you don't mind, I'm gonna keep on asking questions here, to fully grasp how this adjusted proposal would work in practice.

---

> The need for a `selector()` function at all stands out to me as an issue

I see that `animation-timeline: scroll(…)` accepts a `container-name` which identifies a container. To me it feels kinda the same, but simply shifted: you still need an identifier. Here in the form of a container-name, instead of an id _(or any selector if it were to behave like `document.querySelector`)_ with `selector()`.

However, I do see a reduced number of identifiers with this:

```css
main { /* Identifier 1 */
  container-type: size;
  container-name: page-layout; /* Identifier 2 */
}

.foo {
  animation-timeline: scroll(block, page-layout); /* Identifier 2, again */
}
```

vs.

```css
main { /* Identifier 1 */
  container-type: size;
  container-name: page-layout; /* Identifier 2 */
}

@scroll-timeline my-timeline {  /* Identifier 3 */
  source: selector(main);  /* Identifier 1, again */
  direction: block;
}

.foo {
  animation-timeline: my-timeline; /* Identifier 3, again */
}
```

That's one identifier less, so I guess that's a win there :)

On the other hand: when using a `scroll-timeline-name` — when the animated element is not a child of the scroll container — you'd also have three identifiers again:

```css
main { /* Identifier 1 */
  container-type: size;
  container-name: page-layout; /* Identifier 2 */
  scroll-timeline-direction: block;
  scroll-timeline-name: main-scroller: /* Identifier 3 */
}

.foo {
  animation-timeline: scroller; /* Identifier 3, again */
}
```

As a sidenote: in the snippet above it feels weird to have three identifiers linked to one and the same element. Should more future additions to CSS also require a name, the list of properties with a set name would keep on growing.

Winging back to `selector()` _(sorry, couldn't resist 😅)_:

```css
main {
  container-type: size;
  scroll-timeline-direction: block;
}

@container selector(main) (block-size > 12em) {
  /* … */
}

.foo {
  animation-timeline: selector(main);
}

Feels much neater, no? _(See this as an addendum/alternative syntax, not a replacement for giving names via the `*-name` properties)_

---

> We already have a syntax for attaching properties to selectors (it's the core of the language)

Of course, and we should embrace that where possible.

While working with scroll-timeline _(the current version)_ I often found myself targeting three things. Some using a selector, others using `selector()`:

1. The scroll-container _(using `selector()`)_
1. The element(s) used in element-based offsets _(using `selector()`)_
1. The element that need to be animated. _(using a selector)_

See for example https://codepen.io/bramus/pen/QWGbOBQ which sports a horizontal scrolling section. The code targets:

1. The viewport scroller as the scroll-container
1. The `#sectionPin` as the element-based offset
1. The `.pin-wrap` as the element that needs to be animated

With the adjustments, I guess this be the correct way to do it:

1. Declare `view-timeline-name: sectionpin` on `#sectionPin` so that it's the tracked element _(inside the main viewport scroller)_.
1. Declare `animation-timeline: sectionpin` on `.pin-wrap` so that it animates while `#sectionPin` is visible inside its scroller.

That's correct?

---

> `view-timeline-name` - Specifies a name for this element's in-view timeline, so that it can be referenced by descendant and sibling elements as their animation-timeline.

For the code example referenced above that does seem to work out _(if my understanding is correct there)_ but for a typical ScrollSpy it would not. See a reduced https://codepen.io/bramus/pen/3d544d1a7866478fae98ef39cf4f9b7f demo where the navigation `<nav>` positioned underneath the slider `#s` is not a descendant of the slider `#s` itself.

```html
  <div>
      <ul id="s">
         <li id="s1">Slide 1</li>
         <li id="s2">Slide 2</li>
         <li id="s3">Slide 3</li>
         <li id="s4">Slide 4</li>
      </ul>
   </div>
   
   <nav>
      <a href="#s1" id="d1">Go to Slide 1</a>
      <a href="#s2" id="d2">Go to Slide 2</a>
      <a href="#s3" id="d3">Go to Slide 3</a>
      <a href="#s4" id="d4">Go to Slide 4</a>
   </nav>
```

For example: as `#s2` slides into its parent `#s`, the nav element `#d2` is animated. With the scope limitation mentioned, declaring  `view-timeline-name: s2` on `#s2` will only make that timeline available for descendants/siblings of `#s2`.

This would be something I'd miss to be honest.

---

> Often animations are desired to start and end while a particular element is in view within the scroller.

Often it is also required to perform an animation as an element slides into the scroller, or slides out of it — e.g. not only while it is in view.  See https://codepen.io/bramus/pen/oNYEgEQ for example where elements are animated as the enter/exit the scroller.

How would this be covered in this proposal?

I guess it has to do with the `view-timeline-inset` property that's being mentioned. However, it explicitly states that _“Percentages are with reference to the scrollport.”_, which makes this one not usable for this use-case.

The `view-timeline-fit` also doesn't seem to work out as — at least that's how I interpreted it — it either allows you to animate from the moment an edge touches the scrollport _(”from the moment any part of the box comes into view”)_ or when the targetted element is entirely visible _(contained)_ inside the scrollport _("from the moment all parts of the box come into view")_

Or would one need a combination of both these properties?

Put differently: is it possible to target these 4 typical timelines?

- `#element` is intersecting scrollport, even for the tiniest bit: _(`view-timeline-fit: cover` I guess?)_
- `#element` is in between scrollport edges: _(`view-timeline-fit: contain` I guess?)_
- `#element` is entering from bottom into scrollport: _(?)_
- `#element` is exiting at top from scrollport: _(?)_

Must say I kinda liked the re-use of the threshold concept _(from `IntersectionObserver`)_ in the current proposal which allows you to do this. If there's no way to do this in the adjusted proposal yet, perhaps `view-timeline-inset` could be extended to also accept a `<number>` that resembles the threshold?

---

> Specifies whether the in-view timeline is measured from the moment any part of the box comes into view until all parts leave it (cover/0%) or whether it is measured from the moment all parts of the box come into view until any part leaves it (contain/100%). Initial value is 100% (cover).

Is it possible that there's a typo there and that the very last words should be “… 100% (**contain**).”?

-- 
GitHub Notification of comment by bramus
Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/6674#issuecomment-927378865 using your GitHub account


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

Received on Sunday, 26 September 2021 21:58:11 UTC